mycomesh-consumer 0.1.30 → 0.1.32
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 +49 -111
- package/package.json +7 -5
- package/src/cli.mjs +1 -1
- package/src/consumer-runtime.mjs +1180 -0
- package/src/consumer.mjs +197 -118
- package/consumer.compose.yml +0 -79
- package/scripts/start-consumer.sh +0 -218
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -Eeuo pipefail
|
|
3
|
-
|
|
4
|
-
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
5
|
-
COMPOSE_FILE="$SCRIPT_DIR/../consumer.compose.yml"
|
|
6
|
-
PROJECT_NAME="mycomesh-consumer"
|
|
7
|
-
NODE_IMAGE="${MYCOMESH_NODE_IMAGE:-}"
|
|
8
|
-
CODEX_COMMAND="${MYCOMESH_CODEX_COMMAND:-codex}"
|
|
9
|
-
READY_TIMEOUT="${MYCOMESH_CONSUMER_READY_TIMEOUT_SECONDS:-1800}"
|
|
10
|
-
PROXY_URL="${MYCOMESH_CONSUMER_PROXY:-}"
|
|
11
|
-
NO_BROWSER=0
|
|
12
|
-
NO_CODEX=0
|
|
13
|
-
STOP=0
|
|
14
|
-
RESET_LOCAL=0
|
|
15
|
-
DRY_RUN=0
|
|
16
|
-
CODEX_ARGS=()
|
|
17
|
-
|
|
18
|
-
die() {
|
|
19
|
-
printf 'error: %s\n' "$*" >&2
|
|
20
|
-
exit 64
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
is_docker_cli() {
|
|
24
|
-
local candidate="${1-}" version_output
|
|
25
|
-
[[ -n "$candidate" && -x "$candidate" && ! -d "$candidate" ]] || return 1
|
|
26
|
-
case "$candidate" in */node_modules/*) return 1 ;; esac
|
|
27
|
-
version_output="$("$candidate" --version 2>/dev/null)" || return 1
|
|
28
|
-
[[ "$version_output" == "Docker version "* ]] || return 1
|
|
29
|
-
"$candidate" compose version >/dev/null 2>&1 || return 1
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
find_docker_cli() {
|
|
33
|
-
local configured="${MYCOMESH_DOCKER_CLI:-}" path_entry candidate name fallback old_ifs="$IFS"
|
|
34
|
-
if [[ -n "$configured" ]]; then
|
|
35
|
-
candidate="$configured"
|
|
36
|
-
[[ "$candidate" == */* ]] || candidate="$(command -v "$candidate" 2>/dev/null || true)"
|
|
37
|
-
is_docker_cli "$candidate" || die "MYCOMESH_DOCKER_CLI is not a Docker CLI with Compose V2"
|
|
38
|
-
printf '%s' "$candidate"
|
|
39
|
-
return
|
|
40
|
-
fi
|
|
41
|
-
IFS=:
|
|
42
|
-
for path_entry in ${PATH:-}; do
|
|
43
|
-
[[ -n "$path_entry" ]] || path_entry=.
|
|
44
|
-
for name in docker docker.exe; do
|
|
45
|
-
candidate="$path_entry/$name"
|
|
46
|
-
if is_docker_cli "$candidate"; then
|
|
47
|
-
IFS="$old_ifs"
|
|
48
|
-
printf '%s' "$candidate"
|
|
49
|
-
return
|
|
50
|
-
fi
|
|
51
|
-
done
|
|
52
|
-
done
|
|
53
|
-
IFS="$old_ifs"
|
|
54
|
-
for fallback in /usr/local/bin/docker /opt/homebrew/bin/docker /usr/bin/docker \
|
|
55
|
-
/Applications/Docker.app/Contents/Resources/bin/docker \
|
|
56
|
-
'/c/Program Files/Docker/Docker/resources/bin/docker.exe'; do
|
|
57
|
-
if is_docker_cli "$fallback"; then
|
|
58
|
-
printf '%s' "$fallback"
|
|
59
|
-
return
|
|
60
|
-
fi
|
|
61
|
-
done
|
|
62
|
-
die "Docker Desktop/Engine with Compose V2 is required"
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
rewrite_loopback_proxy() {
|
|
66
|
-
local value="${1-}" scheme authority suffix userinfo host_port tail=""
|
|
67
|
-
case "$value" in *$'\n'*|*$'\r'*) die "Consumer proxy URLs must be single-line values" ;; esac
|
|
68
|
-
if [[ ! "$value" =~ ^([A-Za-z][A-Za-z0-9+.-]*://)([^/?#]*)(.*)$ ]]; then
|
|
69
|
-
printf '%s' "$value"
|
|
70
|
-
return
|
|
71
|
-
fi
|
|
72
|
-
scheme="${BASH_REMATCH[1]}"; authority="${BASH_REMATCH[2]}"; suffix="${BASH_REMATCH[3]}"
|
|
73
|
-
userinfo=""; host_port="$authority"
|
|
74
|
-
if [[ "$authority" == *@* ]]; then userinfo="${authority%@*}@"; host_port="${authority##*@}"; fi
|
|
75
|
-
if [[ "$host_port" == "127.0.0.1" ]]; then :
|
|
76
|
-
elif [[ "$host_port" == 127.0.0.1:* ]]; then tail="${host_port#127.0.0.1}"
|
|
77
|
-
elif [[ "$host_port" == "[::1]" ]]; then :
|
|
78
|
-
elif [[ "$host_port" == "[::1]:"* ]]; then tail="${host_port#\[::1\]}"
|
|
79
|
-
elif [[ "$host_port" =~ ^[Ll][Oo][Cc][Aa][Ll][Hh][Oo][Ss][Tt](:.*)?$ ]]; then tail="${BASH_REMATCH[1]}"
|
|
80
|
-
else printf '%s' "$value"; return
|
|
81
|
-
fi
|
|
82
|
-
printf '%s' "${scheme}${userinfo}host.docker.internal${tail}${suffix}"
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
prepare_proxy_env() {
|
|
86
|
-
local all_proxy_value no_proxy_value
|
|
87
|
-
all_proxy_value="${MYCOMESH_CONSUMER_ALL_PROXY:-}"
|
|
88
|
-
export MYCOMESH_CONSUMER_HTTP_PROXY="$(rewrite_loopback_proxy "${MYCOMESH_CONSUMER_HTTP_PROXY:-$PROXY_URL}")"
|
|
89
|
-
export MYCOMESH_CONSUMER_HTTPS_PROXY="$(rewrite_loopback_proxy "${MYCOMESH_CONSUMER_HTTPS_PROXY:-$PROXY_URL}")"
|
|
90
|
-
export MYCOMESH_CONSUMER_ALL_PROXY="$(rewrite_loopback_proxy "$all_proxy_value")"
|
|
91
|
-
no_proxy_value="${MYCOMESH_CONSUMER_NO_PROXY:-}"
|
|
92
|
-
export MYCOMESH_CONSUMER_NO_PROXY="${no_proxy_value:+${no_proxy_value},}127.0.0.1,localhost,::1"
|
|
93
|
-
export NO_PROXY="$MYCOMESH_CONSUMER_NO_PROXY"
|
|
94
|
-
export no_proxy="$MYCOMESH_CONSUMER_NO_PROXY"
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
run() {
|
|
98
|
-
if ((DRY_RUN)); then printf '+'; printf ' %q' "$@"; printf '\n'; else "$@"; fi
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
compose() {
|
|
102
|
-
run "$DOCKER" compose --project-name "$PROJECT_NAME" --file "$COMPOSE_FILE" "$@"
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
open_browser() {
|
|
106
|
-
local url="$1" opener=""
|
|
107
|
-
printf 'MycoMesh Consumer credentials: %s\n' "$url"
|
|
108
|
-
((NO_BROWSER)) && return
|
|
109
|
-
case "$(uname -s 2>/dev/null || printf unknown)" in
|
|
110
|
-
Darwin) opener=open ;;
|
|
111
|
-
Linux*) command -v xdg-open >/dev/null 2>&1 && opener=xdg-open ;;
|
|
112
|
-
MINGW*|MSYS*|CYGWIN*)
|
|
113
|
-
if command -v cmd.exe >/dev/null 2>&1; then cmd.exe /c start "" "$url" >/dev/null 2>&1 & return; fi ;;
|
|
114
|
-
esac
|
|
115
|
-
if [[ -n "$opener" ]]; then "$opener" "$url" >/dev/null 2>&1 &
|
|
116
|
-
else printf '%s\n' "Open this URL in a browser to connect a wallet and add prepaid access."; fi
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
while (($#)); do
|
|
120
|
-
case "$1" in
|
|
121
|
-
--node-image) (($# >= 2)) || die "--node-image requires a value"; NODE_IMAGE="$2"; shift 2 ;;
|
|
122
|
-
--codex-command) (($# >= 2)) || die "--codex-command requires a value"; CODEX_COMMAND="$2"; shift 2 ;;
|
|
123
|
-
--ready-timeout) (($# >= 2)) || die "--ready-timeout requires a value"; READY_TIMEOUT="$2"; shift 2 ;;
|
|
124
|
-
--proxy) (($# >= 2)) || die "--proxy requires a value"; PROXY_URL="$2"; shift 2 ;;
|
|
125
|
-
--no-browser) NO_BROWSER=1; shift ;;
|
|
126
|
-
--no-codex) NO_CODEX=1; shift ;;
|
|
127
|
-
--stop) STOP=1; shift ;;
|
|
128
|
-
--reset-local) RESET_LOCAL=1; shift ;;
|
|
129
|
-
--dry-run) DRY_RUN=1; shift ;;
|
|
130
|
-
--) shift; CODEX_ARGS=("$@"); break ;;
|
|
131
|
-
*) die "unknown option: $1" ;;
|
|
132
|
-
esac
|
|
133
|
-
done
|
|
134
|
-
|
|
135
|
-
[[ -f "$COMPOSE_FILE" ]] || die "bundled Consumer Compose file is missing"
|
|
136
|
-
[[ "$NODE_IMAGE" =~ ^[A-Za-z0-9][A-Za-z0-9._/-]*@sha256:[a-f0-9]{64}$ ]] || die "Consumer image must be pinned by digest"
|
|
137
|
-
[[ "$READY_TIMEOUT" =~ ^[1-9][0-9]*$ ]] || die "--ready-timeout must be a positive integer"
|
|
138
|
-
((READY_TIMEOUT <= 86400)) || die "--ready-timeout must not exceed 86400 seconds"
|
|
139
|
-
|
|
140
|
-
DOCKER="$(find_docker_cli)"
|
|
141
|
-
if ((!DRY_RUN)); then "$DOCKER" info >/dev/null 2>&1 || die "Docker Engine/Desktop is not running"; fi
|
|
142
|
-
prepare_proxy_env
|
|
143
|
-
if [[ -n "$MYCOMESH_CONSUMER_HTTP_PROXY$MYCOMESH_CONSUMER_HTTPS_PROXY$MYCOMESH_CONSUMER_ALL_PROXY" ]]; then
|
|
144
|
-
printf '%s\n' "Consumer network: explicit proxy"
|
|
145
|
-
else
|
|
146
|
-
printf '%s\n' "Consumer network: direct"
|
|
147
|
-
fi
|
|
148
|
-
export MYCOMESH_NODE_IMAGE="$NODE_IMAGE"
|
|
149
|
-
|
|
150
|
-
if ((STOP)); then
|
|
151
|
-
compose stop consumer
|
|
152
|
-
printf '%s\n' "MycoMesh Consumer stopped. Its wallet and payment state remain in the Docker volume."
|
|
153
|
-
exit 0
|
|
154
|
-
fi
|
|
155
|
-
|
|
156
|
-
if ((RESET_LOCAL)); then
|
|
157
|
-
if ((DRY_RUN)); then
|
|
158
|
-
printf '%s\n' "Would remove the Consumer containers, network, and protected local volume."
|
|
159
|
-
exit 0
|
|
160
|
-
fi
|
|
161
|
-
printf '%s\n' "This removes the local API key, Consumer identity, wallet metadata and local payment records."
|
|
162
|
-
printf '%s' 'Type RESET to continue: '
|
|
163
|
-
read -r confirmation
|
|
164
|
-
[[ "$confirmation" == RESET ]] || die "local Consumer reset cancelled"
|
|
165
|
-
compose down --volumes --remove-orphans
|
|
166
|
-
printf '%s\n' "Local Consumer state removed. Any pending payment authorization remains managed separately."
|
|
167
|
-
exit 0
|
|
168
|
-
fi
|
|
169
|
-
|
|
170
|
-
compose pull consumer-volume-init consumer
|
|
171
|
-
if ! compose up -d --wait --wait-timeout 90 consumer; then
|
|
172
|
-
printf '%s\n' "Consumer startup failed. Check whether another process owns 127.0.0.1:8110." >&2
|
|
173
|
-
"$DOCKER" compose --project-name "$PROJECT_NAME" --file "$COMPOSE_FILE" logs --tail=120 consumer >&2 || true
|
|
174
|
-
exit 1
|
|
175
|
-
fi
|
|
176
|
-
url="http://127.0.0.1:8110/"
|
|
177
|
-
open_browser "$url"
|
|
178
|
-
|
|
179
|
-
if ((DRY_RUN || NO_CODEX)); then
|
|
180
|
-
printf '%s\n' "MycoMesh Consumer is running at http://127.0.0.1:8110/v1"
|
|
181
|
-
((DRY_RUN)) && printf '%s\n' "Dry run complete; no container or Codex process was started."
|
|
182
|
-
exit 0
|
|
183
|
-
fi
|
|
184
|
-
|
|
185
|
-
printf '%s\n' "Waiting for a healthy Settlement V7 Relay..."
|
|
186
|
-
command -v curl >/dev/null 2>&1 || die "curl is required while waiting for wallet onboarding"
|
|
187
|
-
started_at="$(date +%s)"
|
|
188
|
-
while ! curl --noproxy '*' --fail --silent --max-time 3 http://127.0.0.1:8110/ready >/dev/null 2>&1; do
|
|
189
|
-
if (( $(date +%s) - started_at >= READY_TIMEOUT )); then
|
|
190
|
-
die "timed out waiting for prepaid access; reopen $url"
|
|
191
|
-
fi
|
|
192
|
-
sleep 2
|
|
193
|
-
done
|
|
194
|
-
|
|
195
|
-
if ! codex_env="$("$DOCKER" compose --project-name "$PROJECT_NAME" --file "$COMPOSE_FILE" exec -T consumer python -m gateway.consumer_v7 codex-env)"; then
|
|
196
|
-
die "could not load Codex credentials from the local Consumer"
|
|
197
|
-
fi
|
|
198
|
-
eval "$codex_env"
|
|
199
|
-
unset codex_env
|
|
200
|
-
if ! command -v "$CODEX_COMMAND" >/dev/null 2>&1; then
|
|
201
|
-
printf "error: Consumer is ready, but '%s' is not installed on this host\n" "$CODEX_COMMAND" >&2
|
|
202
|
-
exit 127
|
|
203
|
-
fi
|
|
204
|
-
|
|
205
|
-
printf '%s\n' "Opening Codex through the local MycoMesh Consumer."
|
|
206
|
-
codex_command=(
|
|
207
|
-
"$CODEX_COMMAND"
|
|
208
|
-
-c 'model="gpt-5.5"' \
|
|
209
|
-
-c 'model_provider="mycomesh"' \
|
|
210
|
-
-c 'model_providers.mycomesh.name="MycoMesh"' \
|
|
211
|
-
-c 'model_providers.mycomesh.base_url="http://127.0.0.1:8110/v1"' \
|
|
212
|
-
-c 'model_providers.mycomesh.env_key="OPENAI_API_KEY"' \
|
|
213
|
-
-c 'model_providers.mycomesh.wire_api="responses"'
|
|
214
|
-
)
|
|
215
|
-
if ((${#CODEX_ARGS[@]})); then
|
|
216
|
-
codex_command+=("${CODEX_ARGS[@]}")
|
|
217
|
-
fi
|
|
218
|
-
exec "${codex_command[@]}"
|