@dotdrelle/wiki-manager 0.6.30 → 0.6.31
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/bin/wiki-manager +39 -1
- package/bin/wiki-manager.js +61 -2
- package/package.json +1 -1
- package/src/commands/slash.js +1 -0
- package/src/core/cacert.js +66 -0
- package/src/core/compose.js +9 -7
- package/src/core/env.js +13 -3
- package/src/core/mcp.js +1 -1
- package/wiki-workspace +116 -23
package/bin/wiki-manager
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
|
+
CACERT_PATH="${WIKI_MANAGER_CACERT_PATH:-}"
|
|
5
|
+
ARGS=()
|
|
6
|
+
while [[ $# -gt 0 ]]; do
|
|
7
|
+
case "$1" in
|
|
8
|
+
--cacert)
|
|
9
|
+
[[ $# -ge 2 ]] || { printf 'Error: --cacert requires a file path\n' >&2; exit 2; }
|
|
10
|
+
CACERT_PATH="$2"
|
|
11
|
+
shift 2
|
|
12
|
+
;;
|
|
13
|
+
*)
|
|
14
|
+
ARGS+=("$1")
|
|
15
|
+
shift
|
|
16
|
+
;;
|
|
17
|
+
esac
|
|
18
|
+
done
|
|
19
|
+
|
|
20
|
+
absolute_file_path() {
|
|
21
|
+
local value="$1"
|
|
22
|
+
local dir base
|
|
23
|
+
if [[ "$value" = /* ]]; then
|
|
24
|
+
printf '%s\n' "$value"
|
|
25
|
+
return
|
|
26
|
+
fi
|
|
27
|
+
dir="$(dirname "$value")"
|
|
28
|
+
base="$(basename "$value")"
|
|
29
|
+
printf '%s/%s\n' "$(cd "$dir" && pwd)" "$base"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if [[ -n "$CACERT_PATH" ]]; then
|
|
33
|
+
CACERT_PATH="$(absolute_file_path "$CACERT_PATH")"
|
|
34
|
+
[[ -f "$CACERT_PATH" ]] || { printf 'Error: --cacert file not found: %s\n' "$CACERT_PATH" >&2; exit 2; }
|
|
35
|
+
export WIKI_MANAGER_CACERT_PATH="$CACERT_PATH"
|
|
36
|
+
export NODE_EXTRA_CA_CERTS="$CACERT_PATH"
|
|
37
|
+
export SSL_CERT_FILE="$CACERT_PATH"
|
|
38
|
+
export REQUESTS_CA_BUNDLE="$CACERT_PATH"
|
|
39
|
+
export CURL_CA_BUNDLE="$CACERT_PATH"
|
|
40
|
+
fi
|
|
41
|
+
|
|
4
42
|
BUN_BIN="$(command -v bun 2>/dev/null || true)"
|
|
5
43
|
if [[ -z "$BUN_BIN" && -n "${BUN_INSTALL:-}" && -x "$BUN_INSTALL/bin/bun" ]]; then
|
|
6
44
|
BUN_BIN="$BUN_INSTALL/bin/bun"
|
|
@@ -27,4 +65,4 @@ while [[ -L "$SCRIPT_SOURCE" ]]; do
|
|
|
27
65
|
done
|
|
28
66
|
BIN_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
|
|
29
67
|
|
|
30
|
-
exec "$BUN_BIN" "$BIN_DIR/wiki-manager.js" "
|
|
68
|
+
exec "$BUN_BIN" "$BIN_DIR/wiki-manager.js" "${ARGS[@]}"
|
package/bin/wiki-manager.js
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
function valueAfter(argv, flag) {
|
|
6
|
+
const index = argv.indexOf(flag);
|
|
7
|
+
if (index === -1) return undefined;
|
|
8
|
+
return argv[index + 1];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function stripOptionWithValue(argv, flag) {
|
|
12
|
+
const result = [];
|
|
13
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
14
|
+
if (argv[index] === flag) {
|
|
15
|
+
index += 1;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
result.push(argv[index]);
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function cacertEnvVars(cacert) {
|
|
24
|
+
return {
|
|
25
|
+
WIKI_MANAGER_CACERT_PATH: cacert,
|
|
26
|
+
NODE_EXTRA_CA_CERTS: cacert,
|
|
27
|
+
SSL_CERT_FILE: cacert,
|
|
28
|
+
REQUESTS_CA_BUNDLE: cacert,
|
|
29
|
+
CURL_CA_BUNDLE: cacert,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolveCacert(argv) {
|
|
34
|
+
const cacert = valueAfter(argv, '--cacert');
|
|
35
|
+
if (!cacert) return { argv, cacert: null };
|
|
36
|
+
const absolute = resolve(cacert);
|
|
37
|
+
if (!existsSync(absolute)) {
|
|
38
|
+
throw new Error(`--cacert file not found: ${absolute}`);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
argv: stripOptionWithValue(argv, '--cacert'),
|
|
42
|
+
cacert: absolute,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function reexecWithCacertIfNeeded(argv, cacert) {
|
|
47
|
+
if (!cacert || process.env.WIKI_MANAGER_CACERT_BOOTSTRAPPED === '1') return;
|
|
48
|
+
const { spawnSync } = await import('node:child_process');
|
|
49
|
+
const env = { ...process.env, WIKI_MANAGER_CACERT_BOOTSTRAPPED: '1', ...cacertEnvVars(cacert) };
|
|
50
|
+
const result = spawnSync(process.execPath, [process.argv[1], ...argv], {
|
|
51
|
+
env,
|
|
52
|
+
stdio: 'inherit',
|
|
53
|
+
});
|
|
54
|
+
if (result.error) throw result.error;
|
|
55
|
+
process.exit(result.status ?? 1);
|
|
56
|
+
}
|
|
4
57
|
|
|
5
58
|
function formatStartupError(err) {
|
|
6
59
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -21,7 +74,13 @@ function formatStartupError(err) {
|
|
|
21
74
|
}
|
|
22
75
|
|
|
23
76
|
async function main() {
|
|
24
|
-
const
|
|
77
|
+
const parsed = resolveCacert(process.argv.slice(2));
|
|
78
|
+
const argv = parsed.argv;
|
|
79
|
+
await reexecWithCacertIfNeeded(argv, parsed.cacert);
|
|
80
|
+
// Fallback for already-bootstrapped direct invocations; the shell wrapper
|
|
81
|
+
// exports these before Bun starts.
|
|
82
|
+
if (parsed.cacert) Object.assign(process.env, cacertEnvVars(parsed.cacert));
|
|
83
|
+
await import('@opentui/solid/preload');
|
|
25
84
|
const interactive = process.stdout.isTTY && process.stdin.isTTY && !argv.includes('--headless') && !argv.includes('--once') && !argv.includes('--version') && !argv.includes('-v') && !argv.includes('--help') && !argv.includes('-h');
|
|
26
85
|
if (interactive) process.stdout.write('Starting wiki-manager…\r');
|
|
27
86
|
const { runCli } = await import('../src/cli/wiki-manager.js');
|
package/package.json
CHANGED
package/src/commands/slash.js
CHANGED
|
@@ -562,6 +562,7 @@ Usage:
|
|
|
562
562
|
Options:
|
|
563
563
|
-v, --version Print version
|
|
564
564
|
-h, --help Print help
|
|
565
|
+
--cacert <path> Trust a local CA; Docker must be able to read this host path
|
|
565
566
|
--once <prompt> Run one agent turn and exit
|
|
566
567
|
--headless Run a workspace task non-interactively
|
|
567
568
|
--workspace <name> Workspace for --headless
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import YAML from 'yaml';
|
|
4
|
+
import { managerRuntimeDir } from './env.js';
|
|
5
|
+
|
|
6
|
+
export const CACERT_CONTAINER_PATH = '/wiki-manager-ca.pem';
|
|
7
|
+
export const CACERT_ENV_KEYS = [
|
|
8
|
+
'NODE_EXTRA_CA_CERTS',
|
|
9
|
+
'SSL_CERT_FILE',
|
|
10
|
+
'REQUESTS_CA_BUNDLE',
|
|
11
|
+
'CURL_CA_BUNDLE',
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export function activeCacertPath() {
|
|
15
|
+
const value = process.env.WIKI_MANAGER_CACERT_PATH;
|
|
16
|
+
return value ? resolve(value) : null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function cacertEnv(path = activeCacertPath(), targetPath = path) {
|
|
20
|
+
if (!path) return {};
|
|
21
|
+
return Object.fromEntries(CACERT_ENV_KEYS.map((key) => [key, targetPath]));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parseComposeServices(composeFilePath) {
|
|
25
|
+
const parsed = YAML.parse(readFileSync(composeFilePath, 'utf8')) ?? {};
|
|
26
|
+
return Object.keys(parsed.services ?? {}).filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function composeOverrideContent(cacertPath, services) {
|
|
30
|
+
const serviceEntries = Object.fromEntries(
|
|
31
|
+
services.map((service) => [
|
|
32
|
+
service,
|
|
33
|
+
{
|
|
34
|
+
volumes: [`${cacertPath}:${CACERT_CONTAINER_PATH}:ro`],
|
|
35
|
+
environment: cacertEnv(cacertPath, CACERT_CONTAINER_PATH),
|
|
36
|
+
},
|
|
37
|
+
]),
|
|
38
|
+
);
|
|
39
|
+
const doc = {
|
|
40
|
+
services: serviceEntries,
|
|
41
|
+
};
|
|
42
|
+
return [
|
|
43
|
+
'# Generated by wiki-manager. Safe to delete.',
|
|
44
|
+
'# Rewritten when --cacert is used with a Docker Compose command.',
|
|
45
|
+
YAML.stringify(doc).trimEnd(),
|
|
46
|
+
'',
|
|
47
|
+
].join('\n');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let _cacertOverrideCache;
|
|
51
|
+
|
|
52
|
+
export function ensureCacertComposeOverride(composeFilePath, fileName = 'cacert.compose.yml') {
|
|
53
|
+
if (_cacertOverrideCache !== undefined) return _cacertOverrideCache;
|
|
54
|
+
const cacertPath = activeCacertPath();
|
|
55
|
+
if (!cacertPath) return (_cacertOverrideCache = null);
|
|
56
|
+
if (!existsSync(cacertPath)) {
|
|
57
|
+
throw new Error(`--cacert file not found: ${cacertPath}`);
|
|
58
|
+
}
|
|
59
|
+
const services = parseComposeServices(composeFilePath);
|
|
60
|
+
if (services.length === 0) return null;
|
|
61
|
+
const runtimeDir = managerRuntimeDir();
|
|
62
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
63
|
+
const overridePath = join(runtimeDir, fileName);
|
|
64
|
+
writeFileSync(overridePath, composeOverrideContent(cacertPath, services), 'utf8');
|
|
65
|
+
return (_cacertOverrideCache = overridePath);
|
|
66
|
+
}
|
package/src/core/compose.js
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
import YAML from 'yaml';
|
|
6
|
+
import { cacertEnv, ensureCacertComposeOverride } from './cacert.js';
|
|
6
7
|
import { managerEnvFile, readEnvFile } from './env.js';
|
|
7
8
|
import { managerRoot } from './workspaces.js';
|
|
8
9
|
|
|
@@ -93,14 +94,14 @@ function projectName(session) {
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
function composeBaseArgs(session) {
|
|
96
|
-
const
|
|
97
|
+
const compose = composeFile();
|
|
98
|
+
const cacertOverride = ensureCacertComposeOverride(compose);
|
|
99
|
+
const args = ['compose', '-f', compose];
|
|
100
|
+
if (cacertOverride) args.push('-f', cacertOverride);
|
|
101
|
+
args.push('-p', projectName(session));
|
|
97
102
|
const managerEnvPath = managerEnvFile();
|
|
98
|
-
if (existsSync(managerEnvPath))
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
if (session.workspaceEnvFile && existsSync(session.workspaceEnvFile)) {
|
|
102
|
-
args.push('--env-file', session.workspaceEnvFile);
|
|
103
|
-
}
|
|
103
|
+
if (existsSync(managerEnvPath)) args.push('--env-file', managerEnvPath);
|
|
104
|
+
if (session.workspaceEnvFile && existsSync(session.workspaceEnvFile)) args.push('--env-file', session.workspaceEnvFile);
|
|
104
105
|
return args;
|
|
105
106
|
}
|
|
106
107
|
|
|
@@ -109,6 +110,7 @@ function composeEnv(session) {
|
|
|
109
110
|
...process.env,
|
|
110
111
|
...readManagerEnv(),
|
|
111
112
|
...(session.workspaceEnv ?? {}),
|
|
113
|
+
...cacertEnv(),
|
|
112
114
|
WORKSPACE_NAME: session.workspace,
|
|
113
115
|
WIKI_WORKSPACE_PATH: session.workspacePath,
|
|
114
116
|
};
|
package/src/core/env.js
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { join, resolve } from 'node:path';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
3
|
|
|
4
4
|
export function userManagerDir() {
|
|
5
5
|
return process.cwd();
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export function managerStateDir() {
|
|
9
|
+
return process.env.WIKI_MANAGER_ENV_FILE
|
|
10
|
+
? dirname(resolve(process.env.WIKI_MANAGER_ENV_FILE))
|
|
11
|
+
: userManagerDir();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function managerRuntimeDir() {
|
|
15
|
+
return join(managerStateDir(), '.wiki-manager');
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
export function managerEnvFile() {
|
|
9
19
|
return process.env.WIKI_MANAGER_ENV_FILE
|
|
10
20
|
? resolve(process.env.WIKI_MANAGER_ENV_FILE)
|
|
11
|
-
: join(
|
|
21
|
+
: join(managerStateDir(), '.env');
|
|
12
22
|
}
|
|
13
23
|
|
|
14
24
|
export function managerMcpEndpointsFile() {
|
|
15
|
-
return join(
|
|
25
|
+
return join(managerStateDir(), 'mcp.endpoints.json');
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
function parseEnvValue(value) {
|
package/src/core/mcp.js
CHANGED
|
@@ -211,7 +211,7 @@ async function mcpRequest(endpoint, method, params, signal, options = {}) {
|
|
|
211
211
|
params: {
|
|
212
212
|
protocolVersion: '2025-06-18',
|
|
213
213
|
capabilities: {},
|
|
214
|
-
clientInfo: { name: 'wiki-manager', version: '0.6.
|
|
214
|
+
clientInfo: { name: 'wiki-manager', version: '0.6.31' },
|
|
215
215
|
},
|
|
216
216
|
}),
|
|
217
217
|
});
|
package/wiki-workspace
CHANGED
|
@@ -16,10 +16,66 @@ DEFAULT_MANAGER_DIR="$PWD"
|
|
|
16
16
|
WORKSPACES_DIR="${WIKI_WORKSPACES_DIR:-$DEFAULT_MANAGER_DIR/workspaces}"
|
|
17
17
|
MANAGER_ENV_FILE="${WIKI_MANAGER_ENV_FILE:-$DEFAULT_MANAGER_DIR/.env}"
|
|
18
18
|
MANAGER_ENDPOINTS_FILE="${WIKI_MANAGER_ENDPOINTS_FILE:-$DEFAULT_MANAGER_DIR/mcp.endpoints.json}"
|
|
19
|
+
MANAGER_STATE_DIR="$(cd "$(dirname "$MANAGER_ENV_FILE")" && pwd)"
|
|
20
|
+
MANAGER_RUNTIME_DIR="$MANAGER_STATE_DIR/.wiki-manager"
|
|
21
|
+
CACERT_PATH="${WIKI_MANAGER_CACERT_PATH:-}"
|
|
22
|
+
|
|
23
|
+
normalize_path() {
|
|
24
|
+
local value="$1"
|
|
25
|
+
if command -v wslpath >/dev/null 2>&1 && [[ "$value" =~ ^[A-Za-z]:[\\/] ]]; then
|
|
26
|
+
wslpath -u "$value"
|
|
27
|
+
return
|
|
28
|
+
fi
|
|
29
|
+
printf '%s\n' "$value"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
absolute_path() {
|
|
33
|
+
local value="$1"
|
|
34
|
+
local base="${2:-$ROOT_DIR}"
|
|
35
|
+
value="$(normalize_path "$value")"
|
|
36
|
+
if [[ "$value" = /* ]]; then
|
|
37
|
+
printf '%s\n' "$value"
|
|
38
|
+
else
|
|
39
|
+
printf '%s\n' "$base/$value"
|
|
40
|
+
fi
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
parse_global_options() {
|
|
44
|
+
local parsed=()
|
|
45
|
+
while [[ $# -gt 0 ]]; do
|
|
46
|
+
case "$1" in
|
|
47
|
+
--cacert)
|
|
48
|
+
[[ $# -ge 2 ]] || { printf 'Error: --cacert requires a file path\n' >&2; exit 2; }
|
|
49
|
+
CACERT_PATH="$2"
|
|
50
|
+
shift 2
|
|
51
|
+
;;
|
|
52
|
+
*)
|
|
53
|
+
parsed+=("$1")
|
|
54
|
+
shift
|
|
55
|
+
;;
|
|
56
|
+
esac
|
|
57
|
+
done
|
|
58
|
+
if [[ -n "$CACERT_PATH" ]]; then
|
|
59
|
+
CACERT_PATH="$(absolute_path "$CACERT_PATH" "$PWD")"
|
|
60
|
+
[[ -f "$CACERT_PATH" ]] || { printf 'Error: --cacert file not found: %s\n' "$CACERT_PATH" >&2; exit 2; }
|
|
61
|
+
export WIKI_MANAGER_CACERT_PATH="$CACERT_PATH"
|
|
62
|
+
export NODE_EXTRA_CA_CERTS="$CACERT_PATH"
|
|
63
|
+
export SSL_CERT_FILE="$CACERT_PATH"
|
|
64
|
+
export REQUESTS_CA_BUNDLE="$CACERT_PATH"
|
|
65
|
+
export CURL_CA_BUNDLE="$CACERT_PATH"
|
|
66
|
+
fi
|
|
67
|
+
set -- "${parsed[@]}"
|
|
68
|
+
PARSED_ARGS=("$@")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
PARSED_ARGS=()
|
|
72
|
+
parse_global_options "$@"
|
|
73
|
+
set -- "${PARSED_ARGS[@]}"
|
|
19
74
|
|
|
20
75
|
usage() {
|
|
21
76
|
cat <<'EOF'
|
|
22
77
|
Usage:
|
|
78
|
+
wiki-workspace [--cacert <path>] <command> ...
|
|
23
79
|
wiki-workspace config <workspace> [path]
|
|
24
80
|
wiki-workspace up <workspace>
|
|
25
81
|
wiki-workspace wiki <workspace> <command> [args...]
|
|
@@ -50,6 +106,7 @@ Commands:
|
|
|
50
106
|
Configuration:
|
|
51
107
|
workspaces/<workspace>/.env
|
|
52
108
|
Override directory: WIKI_WORKSPACES_DIR=/path/to/dir
|
|
109
|
+
Local CA: --cacert /absolute/path/to/ca.pem (Docker must be able to read this host path)
|
|
53
110
|
EOF
|
|
54
111
|
}
|
|
55
112
|
|
|
@@ -58,26 +115,6 @@ die() {
|
|
|
58
115
|
exit 1
|
|
59
116
|
}
|
|
60
117
|
|
|
61
|
-
normalize_path() {
|
|
62
|
-
local value="$1"
|
|
63
|
-
if command -v wslpath >/dev/null 2>&1 && [[ "$value" =~ ^[A-Za-z]:[\\/] ]]; then
|
|
64
|
-
wslpath -u "$value"
|
|
65
|
-
return
|
|
66
|
-
fi
|
|
67
|
-
printf '%s\n' "$value"
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
absolute_path() {
|
|
71
|
-
local value="$1"
|
|
72
|
-
local base="${2:-$ROOT_DIR}"
|
|
73
|
-
value="$(normalize_path "$value")"
|
|
74
|
-
if [[ "$value" = /* ]]; then
|
|
75
|
-
printf '%s\n' "$value"
|
|
76
|
-
else
|
|
77
|
-
printf '%s\n' "$base/$value"
|
|
78
|
-
fi
|
|
79
|
-
}
|
|
80
|
-
|
|
81
118
|
workspace_env_file() {
|
|
82
119
|
local workspace="$1"
|
|
83
120
|
printf '%s/%s/.env\n' "$WORKSPACES_DIR" "$workspace"
|
|
@@ -169,9 +206,12 @@ agents_compose() {
|
|
|
169
206
|
[[ -f "$MANAGER_ENV_FILE" ]] && compose_env_args+=(--env-file "$MANAGER_ENV_FILE")
|
|
170
207
|
|
|
171
208
|
_agents_dc() {
|
|
209
|
+
local cacert_args=()
|
|
210
|
+
WORKSPACES_ROOT="$workspaces_root" AGENTS_DATA_DIR="$agents_data_dir" \
|
|
211
|
+
read_lines_into_array cacert_args cacert_compose_args "$agents_compose_file" "agents.cacert.compose.yml"
|
|
172
212
|
WORKSPACES_ROOT="$workspaces_root" AGENTS_DATA_DIR="$agents_data_dir" \
|
|
173
213
|
docker compose --project-directory "$DEFAULT_MANAGER_DIR" \
|
|
174
|
-
"${compose_env_args[@]}" -f "$agents_compose_file" -p wiki-agents "$@"
|
|
214
|
+
"${compose_env_args[@]}" -f "$agents_compose_file" "${cacert_args[@]}" -p wiki-agents "$@"
|
|
175
215
|
}
|
|
176
216
|
|
|
177
217
|
case "$subcommand" in
|
|
@@ -444,13 +484,19 @@ compose_for_workspace() {
|
|
|
444
484
|
local compose_env_args=()
|
|
445
485
|
[[ -f "$MANAGER_ENV_FILE" ]] && compose_env_args+=(--env-file "$MANAGER_ENV_FILE")
|
|
446
486
|
compose_env_args+=(--env-file "$workspace_env")
|
|
487
|
+
local cacert_args=()
|
|
488
|
+
WIKI_WORKSPACE_PATH="$ws_path" \
|
|
489
|
+
WIKI_SERVE_PORT="$serve_port" \
|
|
490
|
+
WIKI_MCP_PORT="$mcp_port" \
|
|
491
|
+
PRODUCTION_MCP_PORT="$prod_port" \
|
|
492
|
+
read_lines_into_array cacert_args cacert_compose_args "$ROOT_DIR/docker-compose.yml" "cacert.compose.yml"
|
|
447
493
|
|
|
448
494
|
WIKI_WORKSPACE_PATH="$ws_path" \
|
|
449
495
|
WIKI_SERVE_PORT="$serve_port" \
|
|
450
496
|
WIKI_MCP_PORT="$mcp_port" \
|
|
451
497
|
PRODUCTION_MCP_PORT="$prod_port" \
|
|
452
498
|
docker compose --project-directory "$DEFAULT_MANAGER_DIR" \
|
|
453
|
-
"${compose_env_args[@]}" -f "$ROOT_DIR/docker-compose.yml" -p "$project" "$@"
|
|
499
|
+
"${compose_env_args[@]}" -f "$ROOT_DIR/docker-compose.yml" "${cacert_args[@]}" -p "$project" "$@"
|
|
454
500
|
}
|
|
455
501
|
|
|
456
502
|
logs_args() {
|
|
@@ -474,6 +520,48 @@ read_lines_into_array() {
|
|
|
474
520
|
done < <("$@")
|
|
475
521
|
}
|
|
476
522
|
|
|
523
|
+
cacert_compose_args() {
|
|
524
|
+
local compose_file="$1"
|
|
525
|
+
local override_name="$2"
|
|
526
|
+
[[ -n "$CACERT_PATH" ]] || return 0
|
|
527
|
+
command -v node >/dev/null 2>&1 || die "--cacert requires node to generate Docker Compose overrides"
|
|
528
|
+
|
|
529
|
+
local services
|
|
530
|
+
services="$(
|
|
531
|
+
ROOT_DIR="$ROOT_DIR" _WIKI_COMPOSE_FILE_PATH="$compose_file" node <<'NODE'
|
|
532
|
+
const { createRequire } = require('node:module');
|
|
533
|
+
const fs = require('node:fs');
|
|
534
|
+
const requireFromPackage = createRequire(`${process.env.ROOT_DIR}/package.json`);
|
|
535
|
+
const YAML = requireFromPackage('yaml');
|
|
536
|
+
const parsed = YAML.parse(fs.readFileSync(process.env._WIKI_COMPOSE_FILE_PATH, 'utf8')) ?? {};
|
|
537
|
+
for (const service of Object.keys(parsed.services ?? {})) {
|
|
538
|
+
console.log(service);
|
|
539
|
+
}
|
|
540
|
+
NODE
|
|
541
|
+
)"
|
|
542
|
+
[[ -n "$services" ]] || return 0
|
|
543
|
+
|
|
544
|
+
mkdir -p "$MANAGER_RUNTIME_DIR"
|
|
545
|
+
local override_path="$MANAGER_RUNTIME_DIR/$override_name"
|
|
546
|
+
{
|
|
547
|
+
printf '# Generated by wiki-manager. Safe to delete.\n'
|
|
548
|
+
printf '# Rewritten when --cacert is used with a Docker Compose command.\n'
|
|
549
|
+
printf 'services:\n'
|
|
550
|
+
while IFS= read -r service || [[ -n "$service" ]]; do
|
|
551
|
+
[[ -n "$service" ]] || continue
|
|
552
|
+
printf ' %s:\n' "$service"
|
|
553
|
+
printf ' volumes:\n'
|
|
554
|
+
printf ' - %s:/wiki-manager-ca.pem:ro\n' "$CACERT_PATH"
|
|
555
|
+
printf ' environment:\n'
|
|
556
|
+
printf ' NODE_EXTRA_CA_CERTS: /wiki-manager-ca.pem\n'
|
|
557
|
+
printf ' SSL_CERT_FILE: /wiki-manager-ca.pem\n'
|
|
558
|
+
printf ' REQUESTS_CA_BUNDLE: /wiki-manager-ca.pem\n'
|
|
559
|
+
printf ' CURL_CA_BUNDLE: /wiki-manager-ca.pem\n'
|
|
560
|
+
done <<< "$services"
|
|
561
|
+
} > "$override_path"
|
|
562
|
+
printf '%s\n' -f "$override_path"
|
|
563
|
+
}
|
|
564
|
+
|
|
477
565
|
run_wiki() {
|
|
478
566
|
local workspace="$1"
|
|
479
567
|
shift
|
|
@@ -623,12 +711,17 @@ config_workspace() {
|
|
|
623
711
|
local compose_env_args=()
|
|
624
712
|
[[ -f "$MANAGER_ENV_FILE" ]] && compose_env_args+=(--env-file "$MANAGER_ENV_FILE")
|
|
625
713
|
compose_env_args+=(--env-file "$env_file")
|
|
714
|
+
local cacert_args=()
|
|
715
|
+
WIKI_WORKSPACE_PATH="$target_path" \
|
|
716
|
+
WIKI_SERVE_PORT="$serve_port" \
|
|
717
|
+
WIKI_MCP_PORT="$mcp_port" \
|
|
718
|
+
read_lines_into_array cacert_args cacert_compose_args "$ROOT_DIR/docker-compose.yml" "cacert.compose.yml"
|
|
626
719
|
|
|
627
720
|
WIKI_WORKSPACE_PATH="$target_path" \
|
|
628
721
|
WIKI_SERVE_PORT="$serve_port" \
|
|
629
722
|
WIKI_MCP_PORT="$mcp_port" \
|
|
630
723
|
docker compose --project-directory "$DEFAULT_MANAGER_DIR" \
|
|
631
|
-
"${compose_env_args[@]}" -f "$ROOT_DIR/docker-compose.yml" run --rm wiki init
|
|
724
|
+
"${compose_env_args[@]}" -f "$ROOT_DIR/docker-compose.yml" "${cacert_args[@]}" run --rm wiki init
|
|
632
725
|
|
|
633
726
|
printf 'Workspace ready: %s\n' "$target_path"
|
|
634
727
|
printf 'Start with: wiki-workspace up %s\n' "$workspace"
|