@agentshouse/kit 0.1.0-alpha.4 → 0.1.0-alpha.41
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 +41 -1671
- package/bin/connect-linux.sh +501 -53
- package/bin/connect-windows.ps1 +440 -0
- package/bin/kit.js +200 -159
- package/bootstrap.json +28 -0
- package/docs/configuration.md +104 -0
- package/docs/google.md +33 -0
- package/docs/linux.md +77 -0
- package/docs/macos.md +26 -0
- package/docs/telegram.md +29 -0
- package/docs/windows.md +37 -0
- package/package.json +7 -2
- package/src/adapter-mcp.js +92 -12
- package/src/agents.js +63 -8
- package/src/binding.js +52 -0
- package/src/blocks.js +2 -26
- package/src/bridge.js +28 -14
- package/src/bytes.js +19 -8
- package/src/configuration.js +14 -211
- package/src/connector-login.js +3 -84
- package/src/contract.js +44 -12
- package/src/conversation-originals.js +1 -3
- package/src/delivery.js +4 -7
- package/src/directory.js +6 -26
- package/src/draft.js +4 -82
- package/src/git-main.js +138 -0
- package/src/git.js +62 -0
- package/src/google/calendar.js +39 -45
- package/src/google/drive.js +61 -186
- package/src/google/entries.js +349 -0
- package/src/google/gateway.js +3 -6
- package/src/google/gmail.js +33 -23
- package/src/google/oauth.js +106 -66
- package/src/google/source.js +21 -23
- package/src/host.js +6 -2
- package/src/house-main.js +65 -8
- package/src/house.js +446 -127
- package/src/how-we-work.md +25 -0
- package/src/inbound.js +2 -18
- package/src/kit-work-stream.js +120 -0
- package/src/launcher.js +46 -10
- package/src/local-files.js +3 -11
- package/src/login.js +27 -14
- package/src/mcp.js +18 -0
- package/src/mount.js +9 -18
- package/src/original.js +4 -4
- package/src/pacing.js +41 -0
- package/src/plan.js +37 -45
- package/src/repository.js +3 -61
- package/src/session-bin/git +2 -0
- package/src/setup.js +14 -15
- package/src/skill-set/ask-matt/PHASE-BOUNDARIES.md +55 -0
- package/src/skill-set/ask-matt/SKILL.md +91 -0
- package/src/skill-set/ask-matt/agents/openai.yaml +4 -0
- package/src/skill-set/code-review/LICENSE +21 -0
- package/src/skill-set/code-review/SKILL.md +89 -0
- package/src/skill-set/code-review/agents/openai.yaml +3 -0
- package/src/skill-set/codebase-design/DEEPENING.md +37 -0
- package/src/skill-set/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/src/skill-set/codebase-design/LICENSE +21 -0
- package/src/skill-set/codebase-design/SKILL.md +116 -0
- package/src/skill-set/codebase-design/agents/openai.yaml +3 -0
- package/src/skill-set/diagnosing-bugs/LICENSE +21 -0
- package/src/skill-set/diagnosing-bugs/SKILL.md +140 -0
- package/src/skill-set/diagnosing-bugs/agents/openai.yaml +3 -0
- package/src/skill-set/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
- package/src/skill-set/domain-modeling/ADR-FORMAT.md +47 -0
- package/src/skill-set/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/src/skill-set/domain-modeling/LICENSE +21 -0
- package/src/skill-set/domain-modeling/SKILL.md +76 -0
- package/src/skill-set/domain-modeling/agents/openai.yaml +3 -0
- package/src/skill-set/grill-me/LICENSE +21 -0
- package/src/skill-set/grill-me/SKILL.md +8 -0
- package/src/skill-set/grill-me/agents/openai.yaml +4 -0
- package/src/skill-set/grill-with-docs/LICENSE +21 -0
- package/src/skill-set/grill-with-docs/SKILL.md +8 -0
- package/src/skill-set/grill-with-docs/agents/openai.yaml +4 -0
- package/src/skill-set/grilling/LICENSE +21 -0
- package/src/{starter-set → skill-set}/grilling/SKILL.md +1 -1
- package/src/skill-set/handoff/LICENSE +21 -0
- package/src/skill-set/handoff/SKILL.md +17 -0
- package/src/skill-set/handoff/agents/openai.yaml +4 -0
- package/src/skill-set/implement/LICENSE +21 -0
- package/src/skill-set/implement/SKILL.md +16 -0
- package/src/skill-set/implement/agents/openai.yaml +4 -0
- package/src/skill-set/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/src/skill-set/improve-codebase-architecture/LICENSE +21 -0
- package/src/skill-set/improve-codebase-architecture/SKILL.md +72 -0
- package/src/skill-set/improve-codebase-architecture/agents/openai.yaml +4 -0
- package/src/skill-set/prototype/LICENSE +21 -0
- package/src/skill-set/prototype/LOGIC.md +67 -0
- package/src/skill-set/prototype/SKILL.md +28 -0
- package/src/skill-set/prototype/UI.md +112 -0
- package/src/skill-set/prototype/agents/openai.yaml +3 -0
- package/src/skill-set/research/LICENSE +21 -0
- package/src/skill-set/research/SKILL.md +14 -0
- package/src/skill-set/research/agents/openai.yaml +3 -0
- package/src/skill-set/resolving-merge-conflicts/LICENSE +21 -0
- package/src/skill-set/resolving-merge-conflicts/SKILL.md +16 -0
- package/src/skill-set/resolving-merge-conflicts/agents/openai.yaml +3 -0
- package/src/skill-set/tdd/LICENSE +21 -0
- package/src/skill-set/tdd/SKILL.md +40 -0
- package/src/skill-set/tdd/agents/openai.yaml +3 -0
- package/src/skill-set/tdd/mocking.md +59 -0
- package/src/skill-set/tdd/tests.md +77 -0
- package/src/skill-set/teach/GLOSSARY-FORMAT.md +35 -0
- package/src/skill-set/teach/LEARNING-RECORD-FORMAT.md +46 -0
- package/src/skill-set/teach/LICENSE +21 -0
- package/src/skill-set/teach/MISSION-FORMAT.md +31 -0
- package/src/skill-set/teach/RESOURCES-FORMAT.md +32 -0
- package/src/skill-set/teach/SKILL.md +141 -0
- package/src/skill-set/teach/agents/openai.yaml +4 -0
- package/src/skill-set/to-questionnaire/LICENSE +21 -0
- package/src/skill-set/to-questionnaire/SKILL.md +55 -0
- package/src/skill-set/to-questionnaire/agents/openai.yaml +4 -0
- package/src/skill-set/to-spec/LICENSE +21 -0
- package/src/skill-set/to-spec/SKILL.md +76 -0
- package/src/skill-set/to-spec/agents/openai.yaml +4 -0
- package/src/skill-set/to-tickets/LICENSE +21 -0
- package/src/skill-set/to-tickets/SKILL.md +106 -0
- package/src/skill-set/to-tickets/agents/openai.yaml +4 -0
- package/src/skill-set/wait-what/LICENSE +21 -0
- package/src/skill-set/wait-what/SKILL.md +8 -0
- package/src/skill-set/wait-what/agents/openai.yaml +4 -0
- package/src/skill-set/wayfinder/LICENSE +21 -0
- package/src/skill-set/wayfinder/SKILL.md +129 -0
- package/src/skill-set/wayfinder/agents/openai.yaml +4 -0
- package/src/skill-set/writing-for-agents/LICENSE +21 -0
- package/src/skill-set/writing-for-agents/SKILL-MECHANICS.md +22 -0
- package/src/skill-set/writing-for-agents/SKILL.md +83 -0
- package/src/skill-set/writing-for-agents/agents/openai.yaml +3 -0
- package/src/skill-set.js +85 -0
- package/src/source.js +93 -54
- package/src/state.js +19 -1
- package/src/sync-library.js +7 -11
- package/src/sync-state.js +12 -3
- package/src/sync.js +142 -43
- package/src/tasks.js +92 -0
- package/src/telegram-view.js +217 -0
- package/src/telegram.js +204 -69
- package/src/turn-frames.js +69 -0
- package/src/worker.js +738 -189
- package/src/working-copy.js +1274 -0
- package/src/workspace.js +299 -88
- package/src/google/declared.js +0 -146
- package/src/google/id.js +0 -1
- package/src/instance/google.js +0 -1
- package/src/starter-set.js +0 -17
- /package/src/{starter-set/grilling → skill-set/ask-matt}/LICENSE +0 -0
- /package/src/{starter-set → skill-set}/grilling/agents/openai.yaml +0 -0
package/bin/connect-linux.sh
CHANGED
|
@@ -6,14 +6,395 @@ NAME='house-kit'
|
|
|
6
6
|
HOUSE='https://agents.house'
|
|
7
7
|
WORKSPACE="$HOME/AgentsHouse"
|
|
8
8
|
MANUAL=0
|
|
9
|
+
SKILLS=true
|
|
9
10
|
WORKSPACE_SELECTED=0
|
|
10
11
|
HOUSE_SELECTED=0
|
|
12
|
+
FORWARDING=0
|
|
13
|
+
FORWARDED=kit
|
|
14
|
+
FORWARD=()
|
|
15
|
+
UBUNTU_RELEASES=(jammy noble resolute)
|
|
16
|
+
DOCKER_PACKAGES=(docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin)
|
|
17
|
+
CONFLICTING_PACKAGES=(docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc)
|
|
18
|
+
DOCKER_APP=/Applications/Docker.app
|
|
19
|
+
DESKTOP_WAIT_SECONDS=300
|
|
20
|
+
RUNTIME='Docker Engine'
|
|
21
|
+
OPENER=xdg-open
|
|
22
|
+
NETWORK=(--network host)
|
|
23
|
+
PUBLISHED=()
|
|
24
|
+
AVAILABILITY=intermittent
|
|
25
|
+
NATIVE=0
|
|
26
|
+
NATIVE_RELEASE=26.04
|
|
27
|
+
NATIVE_ARCHITECTURE=amd64
|
|
28
|
+
NATIVE_PACKAGES=(git tmux)
|
|
29
|
+
NATIVE_PREFIX=/opt/house-kit
|
|
30
|
+
NATIVE_SERVICE=house-kit.service
|
|
31
|
+
NATIVE_UNIT=/etc/systemd/system/house-kit.service
|
|
32
|
+
NATIVE_WORKSPACE=/agents/house
|
|
11
33
|
|
|
12
34
|
refuse() {
|
|
13
35
|
printf 'kit_bootstrap_refused: %s\n' "$1" >&2
|
|
14
36
|
exit 1
|
|
15
37
|
}
|
|
16
38
|
|
|
39
|
+
bind_mount() {
|
|
40
|
+
local source=${1//\"/\"\"}
|
|
41
|
+
printf 'type=bind,"src=%s",dst=%s' "$source" "$2"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
native_kit() {
|
|
45
|
+
PATH="$NATIVE_PREFIX/bin:$PATH" HOUSE_KIT_HOME="$KIT_HOME" "$NATIVE_PREFIX/bin/node" "$NATIVE_PREFIX/bin/$1" "${@:2}"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
login_kit() {
|
|
49
|
+
if [[ " $* " == *' --manual '* ]]; then
|
|
50
|
+
if ((NATIVE)); then
|
|
51
|
+
native_kit kit login "$@"
|
|
52
|
+
else
|
|
53
|
+
"${DOCKER_RUN[@]:0:2}" -i "${DOCKER_RUN[@]:2}" login "$@"
|
|
54
|
+
fi
|
|
55
|
+
return
|
|
56
|
+
fi
|
|
57
|
+
command -v "$OPENER" >/dev/null || refuse 'no host browser opener; rerun with --manual'
|
|
58
|
+
if ((NATIVE)); then
|
|
59
|
+
native_kit kit login "$@" --host-browser
|
|
60
|
+
else
|
|
61
|
+
"${DOCKER_RUN[@]:0:2}" ${PUBLISHED[@]+"${PUBLISHED[@]}"} "${DOCKER_RUN[@]:2}" login "$@" --host-browser
|
|
62
|
+
fi | while IFS= read -r line; do
|
|
63
|
+
if [[ "$line" == 'Open '* ]]; then
|
|
64
|
+
printf 'Opening House Login in the host browser.\n'
|
|
65
|
+
"$OPENER" "${line#Open }" >/dev/null 2>&1 || refuse 'host browser did not open; rerun with --manual'
|
|
66
|
+
else
|
|
67
|
+
printf '%s\n' "$line"
|
|
68
|
+
fi
|
|
69
|
+
done
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
start_resident() {
|
|
73
|
+
local network=()
|
|
74
|
+
[[ "$HOUSE" == https://* ]] || network=(--network host)
|
|
75
|
+
docker run -d --name "$NAME" --restart unless-stopped ${network[@]+"${network[@]}"} --user "$(id -u):$(id -g)" --mount "$KIT_HOME_MOUNT" --mount "$WORKSPACE_MOUNT" --label "agentshouse.house=$HOUSE" --env HOME=/kit-home --env HOUSE_KIT_HOME=/kit-home --env HOUSE_KIT_CONTAINER=1 "$IMAGE" resident >/dev/null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
elevated() {
|
|
79
|
+
if ((EUID == 0)); then
|
|
80
|
+
"$@"
|
|
81
|
+
else
|
|
82
|
+
sudo "$@"
|
|
83
|
+
fi
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
docker_member() {
|
|
87
|
+
[[ " $(id -nG "$@") " == *' docker '* ]]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
docker_answers() {
|
|
91
|
+
DOCKER_PLATFORM=$(docker info --format '{{.OSType}}/{{.Architecture}}' 2>/dev/null)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
docker_cause() {
|
|
95
|
+
docker info 2>&1 >/dev/null | tail -n 1
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
unanswered() {
|
|
99
|
+
type -P docker >/dev/null || return 0
|
|
100
|
+
printf '; Docker Engine does not answer: %s' "$(docker_cause)"
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
install_docker_desktop() {
|
|
104
|
+
local mount
|
|
105
|
+
DOWNLOAD=$(mktemp -d) || refuse 'no temporary directory for the Docker Desktop download'
|
|
106
|
+
trap 'rm -rf "$DOWNLOAD"' EXIT
|
|
107
|
+
mount="$DOWNLOAD/volume"
|
|
108
|
+
printf 'Downloading Docker Desktop for %s from docker.com.\n' "$1"
|
|
109
|
+
curl -fsSL -o "$DOWNLOAD/Docker.dmg" "https://desktop.docker.com/mac/main/$ARCH/Docker.dmg" || refuse 'Docker Desktop could not be downloaded'
|
|
110
|
+
printf 'Installing Docker Desktop in /Applications; sudo may ask for your password.\n'
|
|
111
|
+
mkdir "$mount" || refuse 'the Docker Desktop disk image has no mount point'
|
|
112
|
+
elevated hdiutil attach -nobrowse -readonly -mountpoint "$mount" "$DOWNLOAD/Docker.dmg" >/dev/null || refuse 'the Docker Desktop disk image could not be opened'
|
|
113
|
+
if ! elevated "$mount/Docker.app/Contents/MacOS/install" "--user=$(id -un)"; then
|
|
114
|
+
elevated hdiutil detach "$mount" >/dev/null 2>&1 || true
|
|
115
|
+
refuse 'the Docker Desktop installer did not finish'
|
|
116
|
+
fi
|
|
117
|
+
elevated hdiutil detach "$mount" >/dev/null || refuse 'the Docker Desktop disk image could not be closed'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
establish_docker_desktop() {
|
|
121
|
+
PATH="$PATH:$DOCKER_APP/Contents/Resources/bin"
|
|
122
|
+
docker_answers && return
|
|
123
|
+
if ((FORWARDING)); then
|
|
124
|
+
[[ -d "$DOCKER_APP" ]] || refuse 'House Kit is not installed; run this bootstrap without arguments first'
|
|
125
|
+
refuse "Docker Desktop does not answer: $(docker_cause); start Docker Desktop, then rerun this command"
|
|
126
|
+
fi
|
|
127
|
+
[[ -d "$DOCKER_APP" ]] || install_docker_desktop "$1"
|
|
128
|
+
printf 'Starting Docker Desktop; accept its terms or finish its setup if its window asks.\n'
|
|
129
|
+
open "$DOCKER_APP" || refuse 'Docker Desktop could not be opened'
|
|
130
|
+
local waited=0
|
|
131
|
+
until docker_answers; do
|
|
132
|
+
((waited < DESKTOP_WAIT_SECONDS)) || refuse "Docker Desktop is not ready: $(docker_cause); finish what its window asks, then rerun this bootstrap"
|
|
133
|
+
sleep 2
|
|
134
|
+
waited=$((waited + 2))
|
|
135
|
+
done
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
installed_packages() {
|
|
139
|
+
{ dpkg-query -W -f='${db:Status-Status} ${Package}\n' "$@" 2>/dev/null || true; } | awk '$1 == "installed" { print $2 }'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
install_docker_engine() {
|
|
143
|
+
printf 'Installing Docker Engine from Docker'\''s apt repository for %s; sudo may ask for your password.\n' "$1"
|
|
144
|
+
elevated apt-get update -qq >/dev/null || refuse 'apt could not refresh its package lists'
|
|
145
|
+
elevated apt-get install -y -qq ca-certificates curl >/dev/null || refuse 'apt could not install ca-certificates and curl'
|
|
146
|
+
elevated install -m 0755 -d /etc/apt/keyrings || refuse '/etc/apt/keyrings could not be created'
|
|
147
|
+
elevated curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc || refuse 'the Docker apt repository key could not be downloaded'
|
|
148
|
+
elevated chmod a+r /etc/apt/keyrings/docker.asc || refuse 'the Docker apt repository key could not be made readable'
|
|
149
|
+
printf 'Types: deb\nURIs: https://download.docker.com/linux/ubuntu\nSuites: %s\nComponents: stable\nArchitectures: %s\nSigned-By: /etc/apt/keyrings/docker.asc\n' "$2" "$(dpkg --print-architecture)" \
|
|
150
|
+
| elevated tee /etc/apt/sources.list.d/docker.sources >/dev/null || refuse 'the Docker apt repository could not be configured'
|
|
151
|
+
elevated apt-get update -qq >/dev/null || refuse 'apt could not read the Docker apt repository'
|
|
152
|
+
elevated apt-get install -y -qq "${DOCKER_PACKAGES[@]}" >/dev/null || refuse 'apt could not install Docker Engine'
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
establish_docker_engine() {
|
|
156
|
+
docker_answers && return
|
|
157
|
+
if ((EUID != 0)) && ! docker_member && docker_member "$(id -un)"; then
|
|
158
|
+
refuse "$(id -un) joined the docker group after this session began; sign out and back in, then rerun this bootstrap"
|
|
159
|
+
fi
|
|
160
|
+
local distribution='' release='' described='this Linux distribution' conflicting present
|
|
161
|
+
if [[ -r /etc/os-release ]]; then
|
|
162
|
+
distribution=$(. /etc/os-release && printf '%s' "${ID:-}")
|
|
163
|
+
release=$(. /etc/os-release && printf '%s' "${UBUNTU_CODENAME:-${VERSION_CODENAME:-}}")
|
|
164
|
+
described=$(. /etc/os-release && printf '%s' "${PRETTY_NAME:-$described}")
|
|
165
|
+
fi
|
|
166
|
+
if ((FORWARDING)); then
|
|
167
|
+
type -P docker >/dev/null || refuse 'House Kit is not installed; run this bootstrap without arguments first'
|
|
168
|
+
refuse "Docker Engine does not answer: $(docker_cause)"
|
|
169
|
+
fi
|
|
170
|
+
if [[ "$distribution" != ubuntu ]]; then
|
|
171
|
+
type -P docker >/dev/null || refuse "Docker Engine is not installed on $described; install a working Docker Engine, then rerun this bootstrap"
|
|
172
|
+
refuse "Docker Engine does not answer on $described: $(docker_cause)"
|
|
173
|
+
fi
|
|
174
|
+
[[ " ${UBUNTU_RELEASES[*]} " == *" $release "* ]] || refuse "this bootstrap installs Docker Engine only on Ubuntu 22.04, 24.04 and 26.04 LTS, not $described; install a working Docker Engine, then rerun this bootstrap$(unanswered)"
|
|
175
|
+
conflicting=$(installed_packages "${CONFLICTING_PACKAGES[@]}" | paste -sd ' ' -)
|
|
176
|
+
[[ -z "$conflicting" ]] || refuse "the installed packages $conflicting conflict with Docker Engine; remove them or make their Docker Engine work, then rerun this bootstrap$(unanswered)"
|
|
177
|
+
present=$(installed_packages "${DOCKER_PACKAGES[@]}" | wc -l)
|
|
178
|
+
((present == ${#DOCKER_PACKAGES[@]})) || install_docker_engine "$described" "$release"
|
|
179
|
+
if ! systemctl is-active --quiet docker.service; then
|
|
180
|
+
printf 'Starting Docker Engine; sudo may ask for your password.\n'
|
|
181
|
+
elevated systemctl start docker.service || refuse 'Docker Engine could not be started'
|
|
182
|
+
fi
|
|
183
|
+
if ((EUID != 0)); then
|
|
184
|
+
if ! docker_member "$(id -un)"; then
|
|
185
|
+
printf 'Adding %s to the docker group; it applies from your next sign-in, so this run reaches Docker Engine through sudo.\n' "$(id -un)"
|
|
186
|
+
elevated usermod -aG docker "$(id -un)" || refuse "$(id -un) could not be added to the docker group"
|
|
187
|
+
fi
|
|
188
|
+
docker_member || docker() { sudo -u "$(id -un)" docker "$@"; }
|
|
189
|
+
fi
|
|
190
|
+
docker_answers || refuse "Docker Engine does not answer: $(docker_cause)"
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
check_native_host() {
|
|
194
|
+
local distribution='' release='' described=macOS
|
|
195
|
+
if [[ "$RUNTIME" == 'Docker Engine' ]]; then
|
|
196
|
+
described=Linux
|
|
197
|
+
if [[ -r /etc/os-release ]]; then
|
|
198
|
+
distribution=$(. /etc/os-release && printf '%s' "${ID:-}")
|
|
199
|
+
release=$(. /etc/os-release && printf '%s' "${VERSION_ID:-}")
|
|
200
|
+
described=$(. /etc/os-release && printf '%s' "${PRETTY_NAME:-$described}")
|
|
201
|
+
fi
|
|
202
|
+
fi
|
|
203
|
+
[[ "$distribution" == ubuntu && "$release" == "$NATIVE_RELEASE" && "$ARCH" == "$NATIVE_ARCHITECTURE" ]] ||
|
|
204
|
+
refuse "--linux runs only on Ubuntu $NATIVE_RELEASE LTS on $NATIVE_ARCHITECTURE, not $described on $ARCH"
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
establish_native_packages() {
|
|
209
|
+
local present
|
|
210
|
+
present=$(installed_packages "${NATIVE_PACKAGES[@]}" | wc -l)
|
|
211
|
+
((present == ${#NATIVE_PACKAGES[@]})) && return
|
|
212
|
+
printf 'Installing git and tmux from Ubuntu'\''s apt repository; sudo may ask for your password.\n'
|
|
213
|
+
elevated apt-get update -qq >/dev/null || refuse 'apt could not refresh its package lists'
|
|
214
|
+
elevated apt-get install -y -qq "${NATIVE_PACKAGES[@]}" >/dev/null || refuse 'apt could not install git and tmux'
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
stage_native_kit() {
|
|
218
|
+
local copy
|
|
219
|
+
NATIVE_STAGE=$(mktemp -d) || refuse 'no temporary directory for the Kit package'
|
|
220
|
+
trap 'rm -rf "$NATIVE_STAGE"' EXIT
|
|
221
|
+
docker pull --quiet --platform "linux/$ARCH" "$IMAGE" >/dev/null
|
|
222
|
+
copy=$(docker create --platform "linux/$ARCH" "$IMAGE") || refuse 'the Kit image could not be opened'
|
|
223
|
+
mkdir "$NATIVE_STAGE/bin" "$NATIVE_STAGE/lib"
|
|
224
|
+
if ! docker cp --quiet "$copy:/usr/local/bin/node" "$NATIVE_STAGE/bin/node" ||
|
|
225
|
+
! docker cp --quiet "$copy:/usr/local/lib/node_modules" "$NATIVE_STAGE/lib/node_modules"; then
|
|
226
|
+
docker rm "$copy" >/dev/null 2>&1 || true
|
|
227
|
+
refuse 'the Kit package could not be copied from its image'
|
|
228
|
+
fi
|
|
229
|
+
docker rm "$copy" >/dev/null
|
|
230
|
+
ln -s ../lib/node_modules/@agentshouse/kit/bin/kit.js "$NATIVE_STAGE/bin/kit"
|
|
231
|
+
ln -s ../lib/node_modules/@agentshouse/kit/src/session-bin/house "$NATIVE_STAGE/bin/house"
|
|
232
|
+
ln -s ../lib/node_modules/npm/bin/npm-cli.js "$NATIVE_STAGE/bin/npm"
|
|
233
|
+
ln -s ../lib/node_modules/npm/bin/npx-cli.js "$NATIVE_STAGE/bin/npx"
|
|
234
|
+
printf '%s\n' "$IMAGE" > "$NATIVE_STAGE/image"
|
|
235
|
+
chmod 0755 "$NATIVE_STAGE" "$NATIVE_STAGE/bin" "$NATIVE_STAGE/lib"
|
|
236
|
+
chmod 0644 "$NATIVE_STAGE/image"
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
place_native_kit() {
|
|
240
|
+
printf 'Installing House Kit in %s; sudo may ask for your password.\n' "$NATIVE_PREFIX"
|
|
241
|
+
elevated rm -rf "$NATIVE_PREFIX" && elevated mv "$NATIVE_STAGE" "$NATIVE_PREFIX" && elevated chown -R root:root "$NATIVE_PREFIX" ||
|
|
242
|
+
refuse "House Kit could not be installed in $NATIVE_PREFIX"
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
start_native_service() {
|
|
246
|
+
printf '[Unit]\nDescription=House Kit\nWants=network-online.target\nAfter=network-online.target docker.service\n\n[Service]\nUser=%s\nWorkingDirectory=%s\nEnvironment=PATH=%s/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\nExecStart=%s/bin/node %s/bin/kit resident\nRestart=always\nRestartSec=5\n\n[Install]\nWantedBy=multi-user.target\n' \
|
|
247
|
+
"$(id -un)" "$NATIVE_WORKSPACE" "$NATIVE_PREFIX" "$NATIVE_PREFIX" "$NATIVE_PREFIX" | elevated tee "$NATIVE_UNIT" >/dev/null &&
|
|
248
|
+
elevated chmod 0644 "$NATIVE_UNIT" || refuse "$NATIVE_UNIT could not be written"
|
|
249
|
+
elevated systemctl daemon-reload || refuse 'systemd could not read the House Kit service'
|
|
250
|
+
elevated systemctl --quiet enable --now "$NATIVE_SERVICE" || refuse 'the House Kit service could not be started'
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
run_kit() {
|
|
254
|
+
if ((NATIVE)); then
|
|
255
|
+
native_kit kit "$@"
|
|
256
|
+
else
|
|
257
|
+
"${DOCKER_RUN[@]}" "$@"
|
|
258
|
+
fi
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
kit_running() {
|
|
262
|
+
if ((NATIVE)); then
|
|
263
|
+
systemctl is-active --quiet "$NATIVE_SERVICE"
|
|
264
|
+
else
|
|
265
|
+
[[ "$(docker inspect --format '{{.State.Running}}' "$NAME")" == true ]]
|
|
266
|
+
fi
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
kit_installed() {
|
|
270
|
+
if ((NATIVE)); then
|
|
271
|
+
[[ -f "$NATIVE_UNIT" ]]
|
|
272
|
+
else
|
|
273
|
+
docker container inspect "$NAME" >/dev/null 2>&1
|
|
274
|
+
fi
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
installed_image() {
|
|
278
|
+
if ((NATIVE == 0)); then
|
|
279
|
+
docker inspect --format '{{.Config.Image}}' "$NAME"
|
|
280
|
+
elif [[ -f "$NATIVE_PREFIX/image" ]]; then
|
|
281
|
+
cat "$NATIVE_PREFIX/image"
|
|
282
|
+
fi
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
check_installation() {
|
|
286
|
+
if ((NATIVE)); then
|
|
287
|
+
grep -qx "User=$(id -un)" "$NATIVE_UNIT" || refuse 'House Kit runs natively on this host for another account'
|
|
288
|
+
return
|
|
289
|
+
fi
|
|
290
|
+
[[ "$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' "$NAME")" == unless-stopped ]] || refuse 'the installed Kit has a different lifecycle'
|
|
291
|
+
[[ "$(docker inspect --format '{{len .Mounts}}' "$NAME")" == 2 ]] || refuse 'the installed Kit has unexpected mounts'
|
|
292
|
+
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/kit-home"}}{{.Source}}{{end}}{{end}}' "$NAME")" == "$KIT_HOME" ]] || refuse 'the installed Kit uses another Kit home'
|
|
293
|
+
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/kit-home"}}{{.Type}}/{{.RW}}{{end}}{{end}}' "$NAME")" == bind/true ]] || refuse 'the installed Kit home is not a writable bind mount'
|
|
294
|
+
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/agents/house"}}{{.Source}}{{end}}{{end}}' "$NAME")" == "$WORKSPACE" ]] || refuse 'the installed Kit uses another workspace root'
|
|
295
|
+
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/agents/house"}}{{.Type}}/{{.RW}}{{end}}{{end}}' "$NAME")" == bind/true ]] || refuse 'the installed workspace is not a writable bind mount'
|
|
296
|
+
[[ "$(docker inspect --format '{{index .Config.Labels "agentshouse.house"}}' "$NAME")" == "$HOUSE" ]] || refuse 'the installed Kit uses another House origin'
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
forward_kit() {
|
|
300
|
+
if ((NATIVE)); then
|
|
301
|
+
native_kit "$FORWARDED" ${FORWARD[@]+"${FORWARD[@]}"}
|
|
302
|
+
return
|
|
303
|
+
fi
|
|
304
|
+
local placed=() entry=() terminal=() here
|
|
305
|
+
if [[ "$FORWARDED" == house ]]; then
|
|
306
|
+
here=$(pwd -P)
|
|
307
|
+
[[ "$here" == "$WORKSPACE" || "$here" == "$WORKSPACE"/* ]] || refuse "the current directory is outside the workspace $WORKSPACE"
|
|
308
|
+
placed=(--workdir "/agents/house${here#"$WORKSPACE"}")
|
|
309
|
+
entry=(--entrypoint house)
|
|
310
|
+
fi
|
|
311
|
+
if [[ -t 0 && -t 1 ]]; then terminal=(-t); fi
|
|
312
|
+
if [[ -t 0 && ! -t 1 ]]; then
|
|
313
|
+
ECHOED=$(stty -g)
|
|
314
|
+
trap 'stty "$ECHOED"' EXIT
|
|
315
|
+
stty -echo
|
|
316
|
+
fi
|
|
317
|
+
if kit_running; then
|
|
318
|
+
docker exec -i ${terminal[@]+"${terminal[@]}"} ${placed[@]+"${placed[@]}"} "$NAME" "$FORWARDED" ${FORWARD[@]+"${FORWARD[@]}"}
|
|
319
|
+
else
|
|
320
|
+
"${DOCKER_RUN[@]:0:2}" -i ${terminal[@]+"${terminal[@]}"} ${placed[@]+"${placed[@]}"} ${entry[@]+"${entry[@]}"} "${DOCKER_RUN[@]:2}" ${FORWARD[@]+"${FORWARD[@]}"}
|
|
321
|
+
fi
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
start_kit() {
|
|
325
|
+
if ((NATIVE)); then
|
|
326
|
+
start_native_service
|
|
327
|
+
else
|
|
328
|
+
start_resident
|
|
329
|
+
fi
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
update_kit() {
|
|
333
|
+
local stopped=0
|
|
334
|
+
if ((NATIVE)); then
|
|
335
|
+
stage_native_kit
|
|
336
|
+
else
|
|
337
|
+
docker pull --quiet --platform "linux/$ARCH" "$IMAGE" >/dev/null
|
|
338
|
+
fi
|
|
339
|
+
if ! kit_running; then
|
|
340
|
+
stopped=1
|
|
341
|
+
elif ((NATIVE)); then
|
|
342
|
+
native_kit kit resident drain
|
|
343
|
+
else
|
|
344
|
+
docker exec "$NAME" kit resident drain
|
|
345
|
+
fi
|
|
346
|
+
if ((NATIVE)); then
|
|
347
|
+
elevated systemctl stop "$NATIVE_SERVICE" || refuse 'the House Kit service could not be stopped'
|
|
348
|
+
place_native_kit
|
|
349
|
+
else
|
|
350
|
+
docker rm -f "$NAME" >/dev/null
|
|
351
|
+
fi
|
|
352
|
+
rm -f "$KIT_HOME/state/update-drain"
|
|
353
|
+
((stopped == 0)) || run_kit credential check
|
|
354
|
+
start_kit
|
|
355
|
+
printf 'House Kit updated for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
resume_kit() {
|
|
359
|
+
run_kit credential check
|
|
360
|
+
if kit_running; then
|
|
361
|
+
printf 'House Kit is already running for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
|
|
362
|
+
return
|
|
363
|
+
fi
|
|
364
|
+
if ((NATIVE)); then
|
|
365
|
+
elevated systemctl start "$NATIVE_SERVICE" || refuse 'the House Kit service could not be started'
|
|
366
|
+
else
|
|
367
|
+
docker start "$NAME" >/dev/null
|
|
368
|
+
fi
|
|
369
|
+
printf 'House Kit restarted for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
connect_kit() {
|
|
373
|
+
if [[ -f "$KIT_HOME/credential" ]]; then
|
|
374
|
+
run_kit credential check
|
|
375
|
+
else
|
|
376
|
+
local login=()
|
|
377
|
+
if ((HOUSE_SELECTED)); then login+=(--house "$HOUSE"); fi
|
|
378
|
+
if ((MANUAL)); then login+=(--manual); fi
|
|
379
|
+
login_kit ${login[@]+"${login[@]}"}
|
|
380
|
+
fi
|
|
381
|
+
run_kit apply
|
|
382
|
+
start_kit
|
|
383
|
+
printf 'House Kit connected for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if [[ "${1:-}" == --linux && ( "${2:-}" == kit || "${2:-}" == house ) ]]; then
|
|
387
|
+
NATIVE=1
|
|
388
|
+
shift
|
|
389
|
+
fi
|
|
390
|
+
|
|
391
|
+
if [[ "${1:-}" == kit || "${1:-}" == house ]]; then
|
|
392
|
+
FORWARDING=1
|
|
393
|
+
FORWARDED="$1"
|
|
394
|
+
FORWARD=("${@:2}")
|
|
395
|
+
set --
|
|
396
|
+
fi
|
|
397
|
+
|
|
17
398
|
while (($#)); do
|
|
18
399
|
case "$1" in
|
|
19
400
|
--workspace|--house)
|
|
@@ -33,26 +414,80 @@ while (($#)); do
|
|
|
33
414
|
MANUAL=1
|
|
34
415
|
shift
|
|
35
416
|
;;
|
|
417
|
+
--no-skills)
|
|
418
|
+
SKILLS=false
|
|
419
|
+
shift
|
|
420
|
+
;;
|
|
421
|
+
--linux)
|
|
422
|
+
NATIVE=1
|
|
423
|
+
shift
|
|
424
|
+
;;
|
|
36
425
|
*) refuse "unknown argument $1" ;;
|
|
37
426
|
esac
|
|
38
427
|
done
|
|
428
|
+
if ((NATIVE)); then
|
|
429
|
+
((WORKSPACE_SELECTED == 0)) || refuse "--linux keeps its workspace at $NATIVE_WORKSPACE; --workspace is for a container"
|
|
430
|
+
WORKSPACE=$NATIVE_WORKSPACE
|
|
431
|
+
AVAILABILITY=continuous
|
|
432
|
+
elif [[ -e "$NATIVE_UNIT" ]]; then
|
|
433
|
+
refuse 'House Kit runs natively on this host; rerun this bootstrap with --linux'
|
|
434
|
+
fi
|
|
39
435
|
|
|
40
436
|
[[ "$IMAGE" =~ ^ghcr\.io/agentshouse/kit@sha256:[0-9a-f]{64}$ ]] || refuse 'this bootstrap has not been published with an immutable image digest'
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
437
|
+
case "$(uname -s)" in
|
|
438
|
+
Linux)
|
|
439
|
+
case "$(uname -m)" in
|
|
440
|
+
x86_64|amd64) ARCH=amd64 ;;
|
|
441
|
+
aarch64|arm64) ARCH=arm64 ;;
|
|
442
|
+
*) refuse "unsupported Linux architecture $(uname -m)" ;;
|
|
443
|
+
esac
|
|
444
|
+
;;
|
|
445
|
+
Darwin)
|
|
446
|
+
RUNTIME='Docker Desktop'
|
|
447
|
+
OPENER=open
|
|
448
|
+
if [[ "$(sysctl -n hw.optional.arm64 2>/dev/null)" == 1 ]]; then
|
|
449
|
+
ARCH=arm64
|
|
450
|
+
CHIP='Apple silicon'
|
|
451
|
+
else
|
|
452
|
+
ARCH=amd64
|
|
453
|
+
CHIP='an Intel chip'
|
|
454
|
+
fi
|
|
455
|
+
;;
|
|
456
|
+
*) refuse "unsupported host $(uname -s); this bootstrap is for Linux and macOS" ;;
|
|
46
457
|
esac
|
|
458
|
+
((NATIVE == 0)) || check_native_host
|
|
47
459
|
[[ "$WORKSPACE" == /* ]] || refuse 'workspace root must be an absolute path'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
460
|
+
if ((NATIVE && FORWARDING)); then
|
|
461
|
+
[[ -f "$NATIVE_UNIT" ]] || refuse 'House Kit is not installed; run this bootstrap with --linux first'
|
|
462
|
+
else
|
|
463
|
+
if [[ "$RUNTIME" == 'Docker Desktop' ]]; then
|
|
464
|
+
establish_docker_desktop "$CHIP"
|
|
465
|
+
DOCKER_SYSTEM=$(docker info --format '{{.OperatingSystem}}' 2>/dev/null) || refuse "Docker Desktop does not answer: $(docker_cause)"
|
|
466
|
+
[[ "$DOCKER_SYSTEM" == 'Docker Desktop' ]] || refuse "Docker answers from $DOCKER_SYSTEM, not Docker Desktop; stop that engine or switch Docker to Docker Desktop, then rerun this bootstrap"
|
|
467
|
+
else
|
|
468
|
+
establish_docker_engine
|
|
469
|
+
fi
|
|
470
|
+
case "$DOCKER_PLATFORM" in
|
|
471
|
+
linux/x86_64|linux/amd64) DOCKER_ARCH=amd64 ;;
|
|
472
|
+
linux/aarch64|linux/arm64) DOCKER_ARCH=arm64 ;;
|
|
473
|
+
*) refuse "unsupported $RUNTIME platform $DOCKER_PLATFORM" ;;
|
|
474
|
+
esac
|
|
475
|
+
[[ "$DOCKER_ARCH" == "$ARCH" ]] || refuse "host linux/$ARCH does not match $RUNTIME linux/$DOCKER_ARCH"
|
|
476
|
+
fi
|
|
477
|
+
if ((NATIVE)); then
|
|
478
|
+
if ((FORWARDING == 0)) && docker container inspect "$NAME" >/dev/null 2>&1; then
|
|
479
|
+
refuse "House Kit runs in the container $NAME on this computer; remove that container, then rerun this bootstrap with --linux"
|
|
480
|
+
fi
|
|
481
|
+
[[ ! -L "${NATIVE_WORKSPACE%/*}" ]] || refuse "${NATIVE_WORKSPACE%/*} is a symbolic link"
|
|
482
|
+
if [[ ! -e "$NATIVE_WORKSPACE" && ! -L "$NATIVE_WORKSPACE" ]]; then
|
|
483
|
+
printf 'Creating %s for the Agents on this host; sudo may ask for your password.\n' "$NATIVE_WORKSPACE"
|
|
484
|
+
{ [[ -d "${NATIVE_WORKSPACE%/*}" ]] || elevated install -d -m 0755 "${NATIVE_WORKSPACE%/*}"; } &&
|
|
485
|
+
elevated install -d -m 0700 -o "$(id -u)" -g "$(id -g)" "$NATIVE_WORKSPACE" || refuse "$NATIVE_WORKSPACE could not be created"
|
|
486
|
+
fi
|
|
487
|
+
elif ((FORWARDING)); then
|
|
488
|
+
docker container inspect "$NAME" >/dev/null 2>&1 || refuse 'House Kit is not installed; run this bootstrap without arguments first'
|
|
489
|
+
WORKSPACE=$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/agents/house"}}{{.Source}}{{end}}{{end}}' "$NAME")
|
|
490
|
+
fi
|
|
56
491
|
|
|
57
492
|
umask 077
|
|
58
493
|
KIT_HOME="$HOME/.house-kit"
|
|
@@ -60,11 +495,13 @@ for path in "$KIT_HOME" "$WORKSPACE"; do
|
|
|
60
495
|
[[ ! -L "$path" ]] || refuse "$path is a symbolic link"
|
|
61
496
|
mkdir -p -m 700 "$path" || refuse "$path could not be created"
|
|
62
497
|
[[ -d "$path" ]] || refuse "$path is not a directory"
|
|
63
|
-
[[
|
|
498
|
+
[[ -O "$path" ]] || refuse "$path is not owned by this User"
|
|
64
499
|
chmod 700 "$path" || refuse "$path could not be owner-protected"
|
|
65
500
|
done
|
|
66
501
|
KIT_HOME=$(cd "$KIT_HOME" && pwd -P)
|
|
67
502
|
WORKSPACE=$(cd "$WORKSPACE" && pwd -P)
|
|
503
|
+
KIT_HOME_MOUNT=$(bind_mount "$KIT_HOME" /kit-home)
|
|
504
|
+
WORKSPACE_MOUNT=$(bind_mount "$WORKSPACE" /agents/house)
|
|
68
505
|
if [[ -f "$KIT_HOME/credential" || -f "$KIT_HOME/environment" ]] && [[ ! -f "$KIT_HOME/house" ]]; then
|
|
69
506
|
refuse 'stored House origin is missing for an enrolled Environment'
|
|
70
507
|
fi
|
|
@@ -76,52 +513,63 @@ if [[ -f "$KIT_HOME/house" ]]; then
|
|
|
76
513
|
HOUSE="$BOUND_HOUSE"
|
|
77
514
|
fi
|
|
78
515
|
[[ "$HOUSE" == https://* || "$HOUSE" == http://127.0.0.1:* || "$HOUSE" == http://localhost:* ]] || refuse 'House origin must use HTTPS or local loopback HTTP'
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
[[ "$(docker inspect --format '{{len .Mounts}}' "$NAME")" == 2 ]] || refuse 'the installed Kit has unexpected mounts'
|
|
85
|
-
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/kit-home"}}{{.Source}}{{end}}{{end}}' "$NAME")" == "$KIT_HOME" ]] || refuse 'the installed Kit uses another Kit home'
|
|
86
|
-
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/kit-home"}}{{.Type}}/{{.RW}}{{end}}{{end}}' "$NAME")" == bind/true ]] || refuse 'the installed Kit home is not a writable bind mount'
|
|
87
|
-
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/agents/house"}}{{.Source}}{{end}}{{end}}' "$NAME")" == "$WORKSPACE" ]] || refuse 'the installed Kit uses another workspace root'
|
|
88
|
-
[[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/agents/house"}}{{.Type}}/{{.RW}}{{end}}{{end}}' "$NAME")" == bind/true ]] || refuse 'the installed workspace is not a writable bind mount'
|
|
89
|
-
[[ "$(docker inspect --format '{{index .Config.Labels "agentshouse.house"}}' "$NAME")" == "$HOUSE" ]] || refuse 'the installed Kit uses another House origin'
|
|
90
|
-
[[ -f "$KIT_HOME/credential" && -f "$KIT_HOME/environment" && -f "$KIT_HOME/house" ]] || refuse 'the installed Kit has no enrolled authority'
|
|
91
|
-
"${DOCKER_RUN[@]}" credential check --house "$HOUSE"
|
|
92
|
-
if [[ "$(docker inspect --format '{{.State.Running}}' "$NAME")" == true ]]; then
|
|
93
|
-
printf 'House Kit is already running for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
|
|
516
|
+
if ((FORWARDING == 0)); then
|
|
517
|
+
if [[ ! -f "$KIT_HOME/kit.json" ]]; then
|
|
518
|
+
printf '{"availability":"%s","execution_authority":"allow","migrators":[],"instances":[],"clients":[],"host":null,"skills":%s}\n' "$AVAILABILITY" "$SKILLS" > "$KIT_HOME/kit.json"
|
|
519
|
+
elif grep -Eq '"skills"[[:space:]]*:' "$KIT_HOME/kit.json"; then
|
|
520
|
+
sed -E -i.old "s/(\"skills\"[[:space:]]*:[[:space:]]*)(true|false)/\\1$SKILLS/" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
|
|
94
521
|
else
|
|
95
|
-
|
|
96
|
-
printf 'House Kit restarted for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
|
|
522
|
+
sed -E -i.old "1s/^([[:space:]]*)\\{/\\1{\"skills\":$SKILLS,/" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
|
|
97
523
|
fi
|
|
98
|
-
|
|
524
|
+
if ((NATIVE)); then
|
|
525
|
+
sed -E -i.old "s/(\"availability\"[[:space:]]*:[[:space:]]*)\"[^\"]*\"/\\1\"$AVAILABILITY\"/" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
|
|
526
|
+
fi
|
|
527
|
+
rm -f "$KIT_HOME/kit.json.old"
|
|
528
|
+
grep -Eq "\"skills\"[[:space:]]*:[[:space:]]*$SKILLS" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
|
|
529
|
+
((NATIVE == 0)) || grep -Eq "\"availability\"[[:space:]]*:[[:space:]]*\"$AVAILABILITY\"" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
|
|
99
530
|
fi
|
|
100
531
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
532
|
+
if ((NATIVE)); then
|
|
533
|
+
RERUN='with --linux'
|
|
534
|
+
else
|
|
535
|
+
RERUN='without arguments'
|
|
536
|
+
if [[ "$RUNTIME" == 'Docker Desktop' && "$HOUSE" == https://* ]]; then
|
|
537
|
+
NETWORK=()
|
|
538
|
+
LOGIN_PORT=$((49152 + RANDOM % 16384))
|
|
539
|
+
PUBLISHED=(--publish "127.0.0.1:$LOGIN_PORT:$LOGIN_PORT" --env "HOUSE_KIT_LOGIN_PORT=$LOGIN_PORT")
|
|
540
|
+
fi
|
|
541
|
+
DOCKER_RUN=(docker run --rm ${NETWORK[@]+"${NETWORK[@]}"} --user "$(id -u):$(id -g)" --mount "$KIT_HOME_MOUNT" --mount "$WORKSPACE_MOUNT" --env HOME=/kit-home --env HOUSE_KIT_HOME=/kit-home --env HOUSE_KIT_CONTAINER=1 --env "HOUSE_KIT_HOSTNAME=$(hostname)" "$IMAGE")
|
|
105
542
|
fi
|
|
106
543
|
|
|
107
|
-
if
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if ((
|
|
111
|
-
"$
|
|
544
|
+
if kit_installed; then
|
|
545
|
+
check_installation
|
|
546
|
+
[[ -f "$KIT_HOME/credential" && -f "$KIT_HOME/environment" && -f "$KIT_HOME/house" ]] || refuse 'the installed Kit has no enrolled authority'
|
|
547
|
+
if ((FORWARDING)); then
|
|
548
|
+
[[ "$(installed_image)" == "$IMAGE" ]] || refuse "an installed Kit uses a different image; rerun this bootstrap $RERUN to update it"
|
|
549
|
+
if [[ "$FORWARDED" == kit && "${FORWARD[0]:-}" == login ]]; then
|
|
550
|
+
login_kit ${FORWARD[@]+"${FORWARD[@]:1}"}
|
|
551
|
+
exit 0
|
|
552
|
+
fi
|
|
553
|
+
forward_kit
|
|
554
|
+
exit
|
|
555
|
+
fi
|
|
556
|
+
((NATIVE == 0)) || establish_native_packages
|
|
557
|
+
if [[ "$(installed_image)" != "$IMAGE" ]]; then
|
|
558
|
+
update_kit
|
|
112
559
|
else
|
|
113
|
-
|
|
114
|
-
"${DOCKER_RUN[@]}" login --house "$HOUSE" --host-browser | while IFS= read -r line; do
|
|
115
|
-
if [[ "$line" == 'Open '* ]]; then
|
|
116
|
-
printf 'Opening House Login in the host browser.\n'
|
|
117
|
-
xdg-open "${line#Open }" >/dev/null 2>&1 || refuse 'host browser did not open; rerun with --manual'
|
|
118
|
-
else
|
|
119
|
-
printf '%s\n' "$line"
|
|
120
|
-
fi
|
|
121
|
-
done
|
|
560
|
+
resume_kit
|
|
122
561
|
fi
|
|
562
|
+
((NATIVE == 0)) || native_kit kit workspace update
|
|
563
|
+
exit 0
|
|
123
564
|
fi
|
|
124
565
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
566
|
+
if ((NATIVE)); then
|
|
567
|
+
establish_native_packages
|
|
568
|
+
if [[ "$(installed_image)" != "$IMAGE" ]]; then
|
|
569
|
+
stage_native_kit
|
|
570
|
+
place_native_kit
|
|
571
|
+
fi
|
|
572
|
+
else
|
|
573
|
+
docker pull --quiet --platform "linux/$ARCH" "$IMAGE" >/dev/null
|
|
574
|
+
fi
|
|
575
|
+
connect_kit
|