kimaki 0.4.53 → 0.4.54
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/dist/cli.js +55 -46
- package/dist/commands/sqlitedb.js +16 -0
- package/dist/interaction-handler.js +4 -0
- package/dist/logger.js +15 -10
- package/dist/opencode.js +1 -0
- package/package.json +3 -3
- package/src/cli.ts +17 -4
- package/src/commands/sqlitedb.ts +20 -0
- package/src/interaction-handler.ts +5 -0
- package/src/logger.ts +17 -10
- package/src/opencode.ts +1 -0
package/dist/cli.js
CHANGED
|
@@ -307,6 +307,10 @@ async function registerCommands({ token, appId, userCommands = [], agents = [],
|
|
|
307
307
|
.setName('restart-opencode-server')
|
|
308
308
|
.setDescription('Restart the opencode server for this channel only (fixes state/auth/plugins)')
|
|
309
309
|
.toJSON(),
|
|
310
|
+
new SlashCommandBuilder()
|
|
311
|
+
.setName('sqlitedb')
|
|
312
|
+
.setDescription('Show the location of the SQLite database file')
|
|
313
|
+
.toJSON(),
|
|
310
314
|
];
|
|
311
315
|
// Add user-defined commands with -cmd suffix
|
|
312
316
|
for (const cmd of userCommands) {
|
|
@@ -437,54 +441,57 @@ async function run({ restart, addChannels, useWorktrees, enableVoiceChannels })
|
|
|
437
441
|
const forceSetup = Boolean(restart);
|
|
438
442
|
intro('🤖 Discord Bot Setup');
|
|
439
443
|
// Step 0: Check if OpenCode CLI is available
|
|
440
|
-
|
|
441
|
-
if (
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
cancel('OpenCode CLI is required to run this bot');
|
|
448
|
-
process.exit(0);
|
|
449
|
-
}
|
|
450
|
-
const s = spinner();
|
|
451
|
-
s.start('Installing OpenCode CLI...');
|
|
452
|
-
try {
|
|
453
|
-
execSync('curl -fsSL https://opencode.ai/install | bash', {
|
|
454
|
-
stdio: 'inherit',
|
|
455
|
-
shell: '/bin/bash',
|
|
444
|
+
// Skip check if user set OPENCODE_PATH (for custom forks like shuvcode)
|
|
445
|
+
if (!process.env.OPENCODE_PATH) {
|
|
446
|
+
const opencodeCheck = spawnSync(process.platform === 'win32' ? 'where' : 'which', ['opencode'], { shell: true });
|
|
447
|
+
if (opencodeCheck.status !== 0) {
|
|
448
|
+
note('OpenCode CLI is required but not found in your PATH.', '⚠️ OpenCode Not Found');
|
|
449
|
+
const shouldInstall = await confirm({
|
|
450
|
+
message: 'Would you like to install OpenCode right now?',
|
|
456
451
|
});
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
// For the current process, we need to check common installation paths
|
|
460
|
-
const possiblePaths = [
|
|
461
|
-
`${process.env.HOME}/.local/bin/opencode`,
|
|
462
|
-
`${process.env.HOME}/.opencode/bin/opencode`,
|
|
463
|
-
'/usr/local/bin/opencode',
|
|
464
|
-
'/opt/opencode/bin/opencode',
|
|
465
|
-
];
|
|
466
|
-
const installedPath = possiblePaths.find((p) => {
|
|
467
|
-
try {
|
|
468
|
-
fs.accessSync(p, fs.constants.F_OK);
|
|
469
|
-
return true;
|
|
470
|
-
}
|
|
471
|
-
catch (error) {
|
|
472
|
-
cliLogger.debug(`OpenCode path not found at ${p}:`, error instanceof Error ? error.message : String(error));
|
|
473
|
-
return false;
|
|
474
|
-
}
|
|
475
|
-
});
|
|
476
|
-
if (!installedPath) {
|
|
477
|
-
note('OpenCode was installed but may not be available in this session.\n' +
|
|
478
|
-
'Please restart your terminal and run this command again.', '⚠️ Restart Required');
|
|
452
|
+
if (isCancel(shouldInstall) || !shouldInstall) {
|
|
453
|
+
cancel('OpenCode CLI is required to run this bot');
|
|
479
454
|
process.exit(0);
|
|
480
455
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
456
|
+
const s = spinner();
|
|
457
|
+
s.start('Installing OpenCode CLI...');
|
|
458
|
+
try {
|
|
459
|
+
execSync('curl -fsSL https://opencode.ai/install | bash', {
|
|
460
|
+
stdio: 'inherit',
|
|
461
|
+
shell: '/bin/bash',
|
|
462
|
+
});
|
|
463
|
+
s.stop('OpenCode CLI installed successfully!');
|
|
464
|
+
// The install script adds opencode to PATH via shell configuration
|
|
465
|
+
// For the current process, we need to check common installation paths
|
|
466
|
+
const possiblePaths = [
|
|
467
|
+
`${process.env.HOME}/.local/bin/opencode`,
|
|
468
|
+
`${process.env.HOME}/.opencode/bin/opencode`,
|
|
469
|
+
'/usr/local/bin/opencode',
|
|
470
|
+
'/opt/opencode/bin/opencode',
|
|
471
|
+
];
|
|
472
|
+
const installedPath = possiblePaths.find((p) => {
|
|
473
|
+
try {
|
|
474
|
+
fs.accessSync(p, fs.constants.F_OK);
|
|
475
|
+
return true;
|
|
476
|
+
}
|
|
477
|
+
catch (error) {
|
|
478
|
+
cliLogger.debug(`OpenCode path not found at ${p}:`, error instanceof Error ? error.message : String(error));
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
if (!installedPath) {
|
|
483
|
+
note('OpenCode was installed but may not be available in this session.\n' +
|
|
484
|
+
'Please restart your terminal and run this command again.', '⚠️ Restart Required');
|
|
485
|
+
process.exit(0);
|
|
486
|
+
}
|
|
487
|
+
// For subsequent spawn calls in this session, we can use the full path
|
|
488
|
+
process.env.OPENCODE_PATH = installedPath;
|
|
489
|
+
}
|
|
490
|
+
catch (error) {
|
|
491
|
+
s.stop('Failed to install OpenCode CLI');
|
|
492
|
+
cliLogger.error('Installation error:', error instanceof Error ? error.message : String(error));
|
|
493
|
+
process.exit(EXIT_NO_RESTART);
|
|
494
|
+
}
|
|
488
495
|
}
|
|
489
496
|
}
|
|
490
497
|
const db = getDatabase();
|
|
@@ -1391,7 +1398,8 @@ cli
|
|
|
1391
1398
|
.option('-p, --port <port>', 'Local port to expose (required)')
|
|
1392
1399
|
.option('-t, --tunnel-id [id]', 'Tunnel ID (random if omitted)')
|
|
1393
1400
|
.option('-h, --host [host]', 'Local host (default: localhost)')
|
|
1394
|
-
.option('-
|
|
1401
|
+
.option('-d, --domain [domain]', 'Base domain (default: kimaki.xyz)')
|
|
1402
|
+
.option('-s, --server [url]', 'Tunnel server URL (overrides domain)')
|
|
1395
1403
|
.action(async (options) => {
|
|
1396
1404
|
const { runTunnel, parseCommandFromArgv, CLI_NAME } = await import('traforo/run-tunnel');
|
|
1397
1405
|
if (!options.port) {
|
|
@@ -1410,6 +1418,7 @@ cli
|
|
|
1410
1418
|
port,
|
|
1411
1419
|
tunnelId: options.tunnelId,
|
|
1412
1420
|
localHost: options.host,
|
|
1421
|
+
baseDomain: options.domain || 'kimaki.xyz',
|
|
1413
1422
|
serverUrl: options.server,
|
|
1414
1423
|
command: command.length > 0 ? command : undefined,
|
|
1415
1424
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// /sqlitedb command.
|
|
2
|
+
// Prints the current location of the SQLite database to the console.
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { getDataDir } from '../config.js';
|
|
5
|
+
/**
|
|
6
|
+
* Handle the /sqlitedb slash command.
|
|
7
|
+
* Displays the path to the SQLite database file.
|
|
8
|
+
*/
|
|
9
|
+
export async function handleSqliteDbCommand({ command }) {
|
|
10
|
+
const dataDir = getDataDir();
|
|
11
|
+
const dbPath = path.join(dataDir, 'discord-sessions.db');
|
|
12
|
+
await command.reply({
|
|
13
|
+
content: `SQLite database location:\n\`${dbPath}\``,
|
|
14
|
+
ephemeral: true,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -24,6 +24,7 @@ import { handleUndoCommand, handleRedoCommand } from './commands/undo-redo.js';
|
|
|
24
24
|
import { handleUserCommand } from './commands/user-command.js';
|
|
25
25
|
import { handleVerbosityCommand } from './commands/verbosity.js';
|
|
26
26
|
import { handleRestartOpencodeServerCommand } from './commands/restart-opencode-server.js';
|
|
27
|
+
import { handleSqliteDbCommand } from './commands/sqlitedb.js';
|
|
27
28
|
import { createLogger, LogPrefix } from './logger.js';
|
|
28
29
|
const interactionLogger = createLogger(LogPrefix.INTERACTION);
|
|
29
30
|
export function registerInteractionHandler({ discordClient, appId, }) {
|
|
@@ -121,6 +122,9 @@ export function registerInteractionHandler({ discordClient, appId, }) {
|
|
|
121
122
|
case 'restart-opencode-server':
|
|
122
123
|
await handleRestartOpencodeServerCommand({ command: interaction, appId });
|
|
123
124
|
return;
|
|
125
|
+
case 'sqlitedb':
|
|
126
|
+
await handleSqliteDbCommand({ command: interaction, appId });
|
|
127
|
+
return;
|
|
124
128
|
}
|
|
125
129
|
// Handle quick agent commands (ending with -agent suffix, but not the base /agent command)
|
|
126
130
|
if (interaction.commandName.endsWith('-agent') && interaction.commandName !== 'agent') {
|
package/dist/logger.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Prefixed logging utility.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Prefixed logging utility using @clack/prompts for consistent visual style.
|
|
2
|
+
// All log methods use clack's log.message() with appropriate symbols to prevent
|
|
3
|
+
// output interleaving from concurrent async operations.
|
|
4
4
|
import { log as clackLog } from '@clack/prompts';
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path, { dirname } from 'node:path';
|
|
@@ -78,30 +78,35 @@ function getTimestamp() {
|
|
|
78
78
|
function padPrefix(prefix) {
|
|
79
79
|
return prefix.padEnd(MAX_PREFIX_LENGTH);
|
|
80
80
|
}
|
|
81
|
+
function formatMessage(timestamp, prefix, args) {
|
|
82
|
+
return [pc.dim(timestamp), prefix, ...args.map(formatArg)].join(' ');
|
|
83
|
+
}
|
|
84
|
+
const noSpacing = { spacing: 0 };
|
|
81
85
|
export function createLogger(prefix) {
|
|
82
86
|
const paddedPrefix = padPrefix(prefix);
|
|
83
87
|
return {
|
|
84
88
|
log: (...args) => {
|
|
85
89
|
writeToFile('INFO', prefix, args);
|
|
86
|
-
|
|
90
|
+
clackLog.step(formatMessage(getTimestamp(), pc.cyan(paddedPrefix), args), noSpacing);
|
|
87
91
|
},
|
|
88
92
|
error: (...args) => {
|
|
89
93
|
writeToFile('ERROR', prefix, args);
|
|
90
|
-
|
|
91
|
-
clackLog.error([paddedPrefix, ...args.map(formatArg)].join(' '));
|
|
94
|
+
clackLog.error(formatMessage(getTimestamp(), pc.red(paddedPrefix), args), noSpacing);
|
|
92
95
|
},
|
|
93
96
|
warn: (...args) => {
|
|
94
97
|
writeToFile('WARN', prefix, args);
|
|
95
|
-
|
|
96
|
-
clackLog.warn([paddedPrefix, ...args.map(formatArg)].join(' '));
|
|
98
|
+
clackLog.warn(formatMessage(getTimestamp(), pc.yellow(paddedPrefix), args), noSpacing);
|
|
97
99
|
},
|
|
98
100
|
info: (...args) => {
|
|
99
101
|
writeToFile('INFO', prefix, args);
|
|
100
|
-
|
|
102
|
+
clackLog.info(formatMessage(getTimestamp(), pc.blue(paddedPrefix), args), noSpacing);
|
|
101
103
|
},
|
|
102
104
|
debug: (...args) => {
|
|
103
105
|
writeToFile('DEBUG', prefix, args);
|
|
104
|
-
|
|
106
|
+
clackLog.message(formatMessage(getTimestamp(), pc.cyan(paddedPrefix), args), {
|
|
107
|
+
...noSpacing,
|
|
108
|
+
symbol: pc.cyan('│'),
|
|
109
|
+
});
|
|
105
110
|
},
|
|
106
111
|
};
|
|
107
112
|
}
|
package/dist/opencode.js
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "kimaki",
|
|
3
3
|
"module": "index.ts",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.4.
|
|
5
|
+
"version": "0.4.54",
|
|
6
6
|
"repository": "https://github.com/remorses/kimaki",
|
|
7
7
|
"bin": "bin.js",
|
|
8
8
|
"files": [
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"undici": "^7.16.0",
|
|
44
44
|
"xdg-basedir": "^5.1.0",
|
|
45
45
|
"zod": "^4.2.1",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
46
|
+
"traforo": "0.0.5",
|
|
47
|
+
"errore": "^0.10.0"
|
|
48
48
|
},
|
|
49
49
|
"optionalDependencies": {
|
|
50
50
|
"@discordjs/opus": "^0.10.0",
|
package/src/cli.ts
CHANGED
|
@@ -401,6 +401,10 @@ async function registerCommands({
|
|
|
401
401
|
.setName('restart-opencode-server')
|
|
402
402
|
.setDescription('Restart the opencode server for this channel only (fixes state/auth/plugins)')
|
|
403
403
|
.toJSON(),
|
|
404
|
+
new SlashCommandBuilder()
|
|
405
|
+
.setName('sqlitedb')
|
|
406
|
+
.setDescription('Show the location of the SQLite database file')
|
|
407
|
+
.toJSON(),
|
|
404
408
|
]
|
|
405
409
|
|
|
406
410
|
// Add user-defined commands with -cmd suffix
|
|
@@ -608,9 +612,14 @@ async function run({ restart, addChannels, useWorktrees, enableVoiceChannels }:
|
|
|
608
612
|
intro('🤖 Discord Bot Setup')
|
|
609
613
|
|
|
610
614
|
// Step 0: Check if OpenCode CLI is available
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
615
|
+
// Skip check if user set OPENCODE_PATH (for custom forks like shuvcode)
|
|
616
|
+
if (!process.env.OPENCODE_PATH) {
|
|
617
|
+
const opencodeCheck = spawnSync(
|
|
618
|
+
process.platform === 'win32' ? 'where' : 'which',
|
|
619
|
+
['opencode'],
|
|
620
|
+
{ shell: true }
|
|
621
|
+
)
|
|
622
|
+
if (opencodeCheck.status !== 0) {
|
|
614
623
|
note('OpenCode CLI is required but not found in your PATH.', '⚠️ OpenCode Not Found')
|
|
615
624
|
|
|
616
625
|
const shouldInstall = await confirm({
|
|
@@ -670,6 +679,7 @@ async function run({ restart, addChannels, useWorktrees, enableVoiceChannels }:
|
|
|
670
679
|
cliLogger.error('Installation error:', error instanceof Error ? error.message : String(error))
|
|
671
680
|
process.exit(EXIT_NO_RESTART)
|
|
672
681
|
}
|
|
682
|
+
}
|
|
673
683
|
}
|
|
674
684
|
|
|
675
685
|
const db = getDatabase()
|
|
@@ -1860,12 +1870,14 @@ cli
|
|
|
1860
1870
|
.option('-p, --port <port>', 'Local port to expose (required)')
|
|
1861
1871
|
.option('-t, --tunnel-id [id]', 'Tunnel ID (random if omitted)')
|
|
1862
1872
|
.option('-h, --host [host]', 'Local host (default: localhost)')
|
|
1863
|
-
.option('-
|
|
1873
|
+
.option('-d, --domain [domain]', 'Base domain (default: kimaki.xyz)')
|
|
1874
|
+
.option('-s, --server [url]', 'Tunnel server URL (overrides domain)')
|
|
1864
1875
|
.action(
|
|
1865
1876
|
async (options: {
|
|
1866
1877
|
port?: string
|
|
1867
1878
|
tunnelId?: string
|
|
1868
1879
|
host?: string
|
|
1880
|
+
domain?: string
|
|
1869
1881
|
server?: string
|
|
1870
1882
|
}) => {
|
|
1871
1883
|
const { runTunnel, parseCommandFromArgv, CLI_NAME } = await import('traforo/run-tunnel')
|
|
@@ -1889,6 +1901,7 @@ cli
|
|
|
1889
1901
|
port,
|
|
1890
1902
|
tunnelId: options.tunnelId,
|
|
1891
1903
|
localHost: options.host,
|
|
1904
|
+
baseDomain: options.domain || 'kimaki.xyz',
|
|
1892
1905
|
serverUrl: options.server,
|
|
1893
1906
|
command: command.length > 0 ? command : undefined,
|
|
1894
1907
|
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// /sqlitedb command.
|
|
2
|
+
// Prints the current location of the SQLite database to the console.
|
|
3
|
+
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import type { CommandContext } from './types.js'
|
|
6
|
+
import { getDataDir } from '../config.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Handle the /sqlitedb slash command.
|
|
10
|
+
* Displays the path to the SQLite database file.
|
|
11
|
+
*/
|
|
12
|
+
export async function handleSqliteDbCommand({ command }: CommandContext): Promise<void> {
|
|
13
|
+
const dataDir = getDataDir()
|
|
14
|
+
const dbPath = path.join(dataDir, 'discord-sessions.db')
|
|
15
|
+
|
|
16
|
+
await command.reply({
|
|
17
|
+
content: `SQLite database location:\n\`${dbPath}\``,
|
|
18
|
+
ephemeral: true,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -37,6 +37,7 @@ import { handleUndoCommand, handleRedoCommand } from './commands/undo-redo.js'
|
|
|
37
37
|
import { handleUserCommand } from './commands/user-command.js'
|
|
38
38
|
import { handleVerbosityCommand } from './commands/verbosity.js'
|
|
39
39
|
import { handleRestartOpencodeServerCommand } from './commands/restart-opencode-server.js'
|
|
40
|
+
import { handleSqliteDbCommand } from './commands/sqlitedb.js'
|
|
40
41
|
import { createLogger, LogPrefix } from './logger.js'
|
|
41
42
|
|
|
42
43
|
const interactionLogger = createLogger(LogPrefix.INTERACTION)
|
|
@@ -174,6 +175,10 @@ export function registerInteractionHandler({
|
|
|
174
175
|
case 'restart-opencode-server':
|
|
175
176
|
await handleRestartOpencodeServerCommand({ command: interaction, appId })
|
|
176
177
|
return
|
|
178
|
+
|
|
179
|
+
case 'sqlitedb':
|
|
180
|
+
await handleSqliteDbCommand({ command: interaction, appId })
|
|
181
|
+
return
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
// Handle quick agent commands (ending with -agent suffix, but not the base /agent command)
|
package/src/logger.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Prefixed logging utility.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Prefixed logging utility using @clack/prompts for consistent visual style.
|
|
2
|
+
// All log methods use clack's log.message() with appropriate symbols to prevent
|
|
3
|
+
// output interleaving from concurrent async operations.
|
|
4
4
|
|
|
5
5
|
import { log as clackLog } from '@clack/prompts'
|
|
6
6
|
import fs from 'node:fs'
|
|
@@ -91,30 +91,37 @@ function padPrefix(prefix: string): string {
|
|
|
91
91
|
return prefix.padEnd(MAX_PREFIX_LENGTH)
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
function formatMessage(timestamp: string, prefix: string, args: unknown[]): string {
|
|
95
|
+
return [pc.dim(timestamp), prefix, ...args.map(formatArg)].join(' ')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const noSpacing = { spacing: 0 }
|
|
99
|
+
|
|
94
100
|
export function createLogger(prefix: LogPrefixType | string) {
|
|
95
101
|
const paddedPrefix = padPrefix(prefix)
|
|
96
102
|
return {
|
|
97
103
|
log: (...args: unknown[]) => {
|
|
98
104
|
writeToFile('INFO', prefix, args)
|
|
99
|
-
|
|
105
|
+
clackLog.step(formatMessage(getTimestamp(), pc.cyan(paddedPrefix), args), noSpacing)
|
|
100
106
|
},
|
|
101
107
|
error: (...args: unknown[]) => {
|
|
102
108
|
writeToFile('ERROR', prefix, args)
|
|
103
|
-
|
|
104
|
-
clackLog.error([paddedPrefix, ...args.map(formatArg)].join(' '))
|
|
109
|
+
clackLog.error(formatMessage(getTimestamp(), pc.red(paddedPrefix), args), noSpacing)
|
|
105
110
|
},
|
|
106
111
|
warn: (...args: unknown[]) => {
|
|
107
112
|
writeToFile('WARN', prefix, args)
|
|
108
|
-
|
|
109
|
-
clackLog.warn([paddedPrefix, ...args.map(formatArg)].join(' '))
|
|
113
|
+
clackLog.warn(formatMessage(getTimestamp(), pc.yellow(paddedPrefix), args), noSpacing)
|
|
110
114
|
},
|
|
111
115
|
info: (...args: unknown[]) => {
|
|
112
116
|
writeToFile('INFO', prefix, args)
|
|
113
|
-
|
|
117
|
+
clackLog.info(formatMessage(getTimestamp(), pc.blue(paddedPrefix), args), noSpacing)
|
|
114
118
|
},
|
|
115
119
|
debug: (...args: unknown[]) => {
|
|
116
120
|
writeToFile('DEBUG', prefix, args)
|
|
117
|
-
|
|
121
|
+
clackLog.message(formatMessage(getTimestamp(), pc.cyan(paddedPrefix), args), {
|
|
122
|
+
...noSpacing,
|
|
123
|
+
symbol: pc.cyan('│'),
|
|
124
|
+
})
|
|
118
125
|
},
|
|
119
126
|
}
|
|
120
127
|
}
|
package/src/opencode.ts
CHANGED
|
@@ -128,6 +128,7 @@ export async function initializeOpencodeForDirectory(directory: string): Promise
|
|
|
128
128
|
stdio: 'pipe',
|
|
129
129
|
detached: false,
|
|
130
130
|
cwd: directory,
|
|
131
|
+
shell: true, // Required for .cmd files on Windows
|
|
131
132
|
env: {
|
|
132
133
|
...process.env,
|
|
133
134
|
OPENCODE_CONFIG_CONTENT: JSON.stringify({
|