@agentshouse/kit 0.1.0-alpha.3 → 0.1.0-alpha.30

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.
Files changed (142) hide show
  1. package/README.md +697 -260
  2. package/bin/connect-linux.sh +200 -25
  3. package/bin/kit.js +179 -157
  4. package/bootstrap.json +17 -0
  5. package/package.json +7 -2
  6. package/src/adapter-mcp.js +76 -12
  7. package/src/agents.js +63 -8
  8. package/src/binding.js +52 -0
  9. package/src/blocks.js +2 -26
  10. package/src/bridge.js +28 -14
  11. package/src/bytes.js +19 -8
  12. package/src/configuration.js +13 -209
  13. package/src/connector-login.js +3 -84
  14. package/src/contract.js +36 -11
  15. package/src/delivery.js +4 -7
  16. package/src/directory.js +6 -26
  17. package/src/draft.js +4 -82
  18. package/src/git-main.js +138 -0
  19. package/src/git.js +62 -0
  20. package/src/google/calendar.js +39 -45
  21. package/src/google/drive.js +61 -186
  22. package/src/google/entries.js +346 -0
  23. package/src/google/gateway.js +3 -6
  24. package/src/google/gmail.js +33 -23
  25. package/src/google/oauth.js +106 -66
  26. package/src/google/source.js +21 -23
  27. package/src/host.js +6 -2
  28. package/src/house-main.js +65 -8
  29. package/src/house.js +446 -127
  30. package/src/how-we-work.md +25 -0
  31. package/src/inbound.js +2 -18
  32. package/src/kit-work-stream.js +118 -0
  33. package/src/launcher.js +46 -10
  34. package/src/local-files.js +3 -11
  35. package/src/login.js +23 -11
  36. package/src/mcp.js +18 -0
  37. package/src/mount.js +13 -21
  38. package/src/original.js +4 -4
  39. package/src/pacing.js +41 -0
  40. package/src/plan.js +37 -45
  41. package/src/repository.js +3 -61
  42. package/src/session-bin/git +2 -0
  43. package/src/setup.js +14 -15
  44. package/src/skill-set/ask-matt/PHASE-BOUNDARIES.md +55 -0
  45. package/src/skill-set/ask-matt/SKILL.md +91 -0
  46. package/src/skill-set/ask-matt/agents/openai.yaml +4 -0
  47. package/src/skill-set/code-review/LICENSE +21 -0
  48. package/src/skill-set/code-review/SKILL.md +89 -0
  49. package/src/skill-set/code-review/agents/openai.yaml +3 -0
  50. package/src/skill-set/codebase-design/DEEPENING.md +37 -0
  51. package/src/skill-set/codebase-design/DESIGN-IT-TWICE.md +44 -0
  52. package/src/skill-set/codebase-design/LICENSE +21 -0
  53. package/src/skill-set/codebase-design/SKILL.md +116 -0
  54. package/src/skill-set/codebase-design/agents/openai.yaml +3 -0
  55. package/src/skill-set/diagnosing-bugs/LICENSE +21 -0
  56. package/src/skill-set/diagnosing-bugs/SKILL.md +140 -0
  57. package/src/skill-set/diagnosing-bugs/agents/openai.yaml +3 -0
  58. package/src/skill-set/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
  59. package/src/skill-set/domain-modeling/ADR-FORMAT.md +47 -0
  60. package/src/skill-set/domain-modeling/CONTEXT-FORMAT.md +60 -0
  61. package/src/skill-set/domain-modeling/LICENSE +21 -0
  62. package/src/skill-set/domain-modeling/SKILL.md +76 -0
  63. package/src/skill-set/domain-modeling/agents/openai.yaml +3 -0
  64. package/src/skill-set/grill-me/LICENSE +21 -0
  65. package/src/skill-set/grill-me/SKILL.md +8 -0
  66. package/src/skill-set/grill-me/agents/openai.yaml +4 -0
  67. package/src/skill-set/grill-with-docs/LICENSE +21 -0
  68. package/src/skill-set/grill-with-docs/SKILL.md +8 -0
  69. package/src/skill-set/grill-with-docs/agents/openai.yaml +4 -0
  70. package/src/skill-set/grilling/LICENSE +21 -0
  71. package/src/{starter-set → skill-set}/grilling/SKILL.md +1 -1
  72. package/src/skill-set/handoff/LICENSE +21 -0
  73. package/src/skill-set/handoff/SKILL.md +17 -0
  74. package/src/skill-set/handoff/agents/openai.yaml +4 -0
  75. package/src/skill-set/implement/LICENSE +21 -0
  76. package/src/skill-set/implement/SKILL.md +16 -0
  77. package/src/skill-set/implement/agents/openai.yaml +4 -0
  78. package/src/skill-set/improve-codebase-architecture/HTML-REPORT.md +123 -0
  79. package/src/skill-set/improve-codebase-architecture/LICENSE +21 -0
  80. package/src/skill-set/improve-codebase-architecture/SKILL.md +72 -0
  81. package/src/skill-set/improve-codebase-architecture/agents/openai.yaml +4 -0
  82. package/src/skill-set/prototype/LICENSE +21 -0
  83. package/src/skill-set/prototype/LOGIC.md +67 -0
  84. package/src/skill-set/prototype/SKILL.md +28 -0
  85. package/src/skill-set/prototype/UI.md +112 -0
  86. package/src/skill-set/prototype/agents/openai.yaml +3 -0
  87. package/src/skill-set/research/LICENSE +21 -0
  88. package/src/skill-set/research/SKILL.md +14 -0
  89. package/src/skill-set/research/agents/openai.yaml +3 -0
  90. package/src/skill-set/resolving-merge-conflicts/LICENSE +21 -0
  91. package/src/skill-set/resolving-merge-conflicts/SKILL.md +16 -0
  92. package/src/skill-set/resolving-merge-conflicts/agents/openai.yaml +3 -0
  93. package/src/skill-set/tdd/LICENSE +21 -0
  94. package/src/skill-set/tdd/SKILL.md +40 -0
  95. package/src/skill-set/tdd/agents/openai.yaml +3 -0
  96. package/src/skill-set/tdd/mocking.md +59 -0
  97. package/src/skill-set/tdd/tests.md +77 -0
  98. package/src/skill-set/teach/GLOSSARY-FORMAT.md +35 -0
  99. package/src/skill-set/teach/LEARNING-RECORD-FORMAT.md +46 -0
  100. package/src/skill-set/teach/LICENSE +21 -0
  101. package/src/skill-set/teach/MISSION-FORMAT.md +31 -0
  102. package/src/skill-set/teach/RESOURCES-FORMAT.md +32 -0
  103. package/src/skill-set/teach/SKILL.md +141 -0
  104. package/src/skill-set/teach/agents/openai.yaml +4 -0
  105. package/src/skill-set/to-questionnaire/LICENSE +21 -0
  106. package/src/skill-set/to-questionnaire/SKILL.md +55 -0
  107. package/src/skill-set/to-questionnaire/agents/openai.yaml +4 -0
  108. package/src/skill-set/to-spec/LICENSE +21 -0
  109. package/src/skill-set/to-spec/SKILL.md +76 -0
  110. package/src/skill-set/to-spec/agents/openai.yaml +4 -0
  111. package/src/skill-set/to-tickets/LICENSE +21 -0
  112. package/src/skill-set/to-tickets/SKILL.md +106 -0
  113. package/src/skill-set/to-tickets/agents/openai.yaml +4 -0
  114. package/src/skill-set/wait-what/LICENSE +21 -0
  115. package/src/skill-set/wait-what/SKILL.md +8 -0
  116. package/src/skill-set/wait-what/agents/openai.yaml +4 -0
  117. package/src/skill-set/wayfinder/LICENSE +21 -0
  118. package/src/skill-set/wayfinder/SKILL.md +129 -0
  119. package/src/skill-set/wayfinder/agents/openai.yaml +4 -0
  120. package/src/skill-set/writing-for-agents/LICENSE +21 -0
  121. package/src/skill-set/writing-for-agents/SKILL-MECHANICS.md +22 -0
  122. package/src/skill-set/writing-for-agents/SKILL.md +83 -0
  123. package/src/skill-set/writing-for-agents/agents/openai.yaml +3 -0
  124. package/src/skill-set.js +85 -0
  125. package/src/source.js +93 -54
  126. package/src/state.js +19 -1
  127. package/src/sync-library.js +7 -11
  128. package/src/sync-state.js +16 -3
  129. package/src/sync.js +36 -21
  130. package/src/tasks.js +75 -0
  131. package/src/telegram-view.js +214 -0
  132. package/src/telegram.js +161 -66
  133. package/src/turn-frames.js +69 -0
  134. package/src/worker.js +674 -184
  135. package/src/working-copy.js +1221 -0
  136. package/src/workspace.js +40 -32
  137. package/src/google/declared.js +0 -146
  138. package/src/google/id.js +0 -1
  139. package/src/instance/google.js +0 -1
  140. package/src/starter-set.js +0 -17
  141. /package/src/{starter-set/grilling → skill-set/ask-matt}/LICENSE +0 -0
  142. /package/src/{starter-set → skill-set}/grilling/agents/openai.yaml +0 -0
@@ -6,14 +6,144 @@ 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_GROUP=0
11
19
 
12
20
  refuse() {
13
21
  printf 'kit_bootstrap_refused: %s\n' "$1" >&2
14
22
  exit 1
15
23
  }
16
24
 
25
+ bind_mount() {
26
+ local source=${1//\"/\"\"}
27
+ printf 'type=bind,"src=%s",dst=%s' "$source" "$2"
28
+ }
29
+
30
+ login_kit() {
31
+ if [[ " $* " == *' --manual '* ]]; then
32
+ "${DOCKER_RUN[@]:0:2}" -i "${DOCKER_RUN[@]:2}" login "$@"
33
+ return
34
+ fi
35
+ command -v xdg-open >/dev/null || refuse 'no host browser opener; rerun with --manual'
36
+ "${DOCKER_RUN[@]}" login "$@" --host-browser | while IFS= read -r line; do
37
+ if [[ "$line" == 'Open '* ]]; then
38
+ printf 'Opening House Login in the host browser.\n'
39
+ xdg-open "${line#Open }" >/dev/null 2>&1 || refuse 'host browser did not open; rerun with --manual'
40
+ else
41
+ printf '%s\n' "$line"
42
+ fi
43
+ done
44
+ }
45
+
46
+ start_resident() {
47
+ local network=()
48
+ [[ "$HOUSE" == https://* ]] || network=(--network host)
49
+ docker run -d --name "$NAME" --restart unless-stopped "${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
50
+ }
51
+
52
+ docker() {
53
+ if ((DOCKER_GROUP)); then
54
+ sudo -u "$(id -un)" docker "$@"
55
+ else
56
+ command docker "$@"
57
+ fi
58
+ }
59
+
60
+ elevated() {
61
+ if ((EUID == 0)); then
62
+ "$@"
63
+ else
64
+ sudo "$@"
65
+ fi
66
+ }
67
+
68
+ docker_member() {
69
+ [[ " $(id -nG "$@") " == *' docker '* ]]
70
+ }
71
+
72
+ docker_answers() {
73
+ DOCKER_PLATFORM=$(docker info --format '{{.OSType}}/{{.Architecture}}' 2>/dev/null)
74
+ }
75
+
76
+ docker_cause() {
77
+ docker info 2>&1 >/dev/null | tail -n 1
78
+ }
79
+
80
+ unanswered() {
81
+ type -P docker >/dev/null || return 0
82
+ printf '; Docker Engine does not answer: %s' "$(docker_cause)"
83
+ }
84
+
85
+ installed_packages() {
86
+ { dpkg-query -W -f='${db:Status-Status} ${Package}\n' "$@" 2>/dev/null || true; } | awk '$1 == "installed" { print $2 }'
87
+ }
88
+
89
+ install_docker_engine() {
90
+ printf 'Installing Docker Engine from Docker'\''s apt repository for %s; sudo may ask for your password.\n' "$1"
91
+ elevated apt-get update -qq >/dev/null || refuse 'apt could not refresh its package lists'
92
+ elevated apt-get install -y -qq ca-certificates curl >/dev/null || refuse 'apt could not install ca-certificates and curl'
93
+ elevated install -m 0755 -d /etc/apt/keyrings || refuse '/etc/apt/keyrings could not be created'
94
+ 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'
95
+ elevated chmod a+r /etc/apt/keyrings/docker.asc || refuse 'the Docker apt repository key could not be made readable'
96
+ 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)" \
97
+ | elevated tee /etc/apt/sources.list.d/docker.sources >/dev/null || refuse 'the Docker apt repository could not be configured'
98
+ elevated apt-get update -qq >/dev/null || refuse 'apt could not read the Docker apt repository'
99
+ elevated apt-get install -y -qq "${DOCKER_PACKAGES[@]}" >/dev/null || refuse 'apt could not install Docker Engine'
100
+ }
101
+
102
+ establish_docker_engine() {
103
+ docker_answers && return
104
+ if ((EUID != 0)) && ! docker_member && docker_member "$(id -un)"; then
105
+ refuse "$(id -un) joined the docker group after this session began; sign out and back in, then rerun this bootstrap"
106
+ fi
107
+ local distribution='' release='' described='this Linux distribution' conflicting present
108
+ if [[ -r /etc/os-release ]]; then
109
+ distribution=$(. /etc/os-release && printf '%s' "${ID:-}")
110
+ release=$(. /etc/os-release && printf '%s' "${UBUNTU_CODENAME:-${VERSION_CODENAME:-}}")
111
+ described=$(. /etc/os-release && printf '%s' "${PRETTY_NAME:-$described}")
112
+ fi
113
+ if ((FORWARDING)); then
114
+ type -P docker >/dev/null || refuse 'House Kit is not installed; run this bootstrap without arguments first'
115
+ refuse "Docker Engine does not answer: $(docker_cause)"
116
+ fi
117
+ if [[ "$distribution" != ubuntu ]]; then
118
+ type -P docker >/dev/null || refuse "Docker Engine is not installed on $described; install a working Docker Engine, then rerun this bootstrap"
119
+ refuse "Docker Engine does not answer on $described: $(docker_cause)"
120
+ fi
121
+ [[ " ${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)"
122
+ conflicting=$(installed_packages "${CONFLICTING_PACKAGES[@]}" | paste -sd ' ' -)
123
+ [[ -z "$conflicting" ]] || refuse "the installed packages $conflicting conflict with Docker Engine; remove them or make their Docker Engine work, then rerun this bootstrap$(unanswered)"
124
+ present=$(installed_packages "${DOCKER_PACKAGES[@]}" | wc -l)
125
+ ((present == ${#DOCKER_PACKAGES[@]})) || install_docker_engine "$described" "$release"
126
+ if ! systemctl is-active --quiet docker.service; then
127
+ printf 'Starting Docker Engine; sudo may ask for your password.\n'
128
+ elevated systemctl start docker.service || refuse 'Docker Engine could not be started'
129
+ fi
130
+ if ((EUID != 0)); then
131
+ if ! docker_member "$(id -un)"; then
132
+ 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)"
133
+ elevated usermod -aG docker "$(id -un)" || refuse "$(id -un) could not be added to the docker group"
134
+ fi
135
+ docker_member || DOCKER_GROUP=1
136
+ fi
137
+ docker_answers || refuse "Docker Engine does not answer: $(docker_cause)"
138
+ }
139
+
140
+ if [[ "${1:-}" == kit || "${1:-}" == house ]]; then
141
+ FORWARDING=1
142
+ FORWARDED="$1"
143
+ FORWARD=("${@:2}")
144
+ set --
145
+ fi
146
+
17
147
  while (($#)); do
18
148
  case "$1" in
19
149
  --workspace|--house)
@@ -33,6 +163,10 @@ while (($#)); do
33
163
  MANUAL=1
34
164
  shift
35
165
  ;;
166
+ --no-skills)
167
+ SKILLS=false
168
+ shift
169
+ ;;
36
170
  *) refuse "unknown argument $1" ;;
37
171
  esac
38
172
  done
@@ -45,14 +179,17 @@ case "$(uname -m)" in
45
179
  *) refuse "unsupported Linux architecture $(uname -m)" ;;
46
180
  esac
47
181
  [[ "$WORKSPACE" == /* ]] || refuse 'workspace root must be an absolute path'
48
- command -v docker >/dev/null || refuse 'Docker Engine client is unavailable'
49
- DOCKER_PLATFORM=$(docker info --format '{{.OSType}}/{{.Architecture}}' 2>/dev/null) || refuse 'Docker Engine is unavailable'
182
+ establish_docker_engine
50
183
  case "$DOCKER_PLATFORM" in
51
184
  linux/x86_64|linux/amd64) DOCKER_ARCH=amd64 ;;
52
185
  linux/aarch64|linux/arm64) DOCKER_ARCH=arm64 ;;
53
186
  *) refuse "unsupported Docker Engine platform $DOCKER_PLATFORM" ;;
54
187
  esac
55
188
  [[ "$DOCKER_ARCH" == "$ARCH" ]] || refuse "host linux/$ARCH does not match Docker Engine linux/$DOCKER_ARCH"
189
+ if ((FORWARDING)); then
190
+ docker container inspect "$NAME" >/dev/null 2>&1 || refuse 'House Kit is not installed; run this bootstrap without arguments first'
191
+ WORKSPACE=$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/agents/house"}}{{.Source}}{{end}}{{end}}' "$NAME")
192
+ fi
56
193
 
57
194
  umask 077
58
195
  KIT_HOME="$HOME/.house-kit"
@@ -65,6 +202,8 @@ for path in "$KIT_HOME" "$WORKSPACE"; do
65
202
  done
66
203
  KIT_HOME=$(cd "$KIT_HOME" && pwd -P)
67
204
  WORKSPACE=$(cd "$WORKSPACE" && pwd -P)
205
+ KIT_HOME_MOUNT=$(bind_mount "$KIT_HOME" /kit-home)
206
+ WORKSPACE_MOUNT=$(bind_mount "$WORKSPACE" /agents/house)
68
207
  if [[ -f "$KIT_HOME/credential" || -f "$KIT_HOME/environment" ]] && [[ ! -f "$KIT_HOME/house" ]]; then
69
208
  refuse 'stored House origin is missing for an enrolled Environment'
70
209
  fi
@@ -76,10 +215,21 @@ if [[ -f "$KIT_HOME/house" ]]; then
76
215
  HOUSE="$BOUND_HOUSE"
77
216
  fi
78
217
  [[ "$HOUSE" == https://* || "$HOUSE" == http://127.0.0.1:* || "$HOUSE" == http://localhost:* ]] || refuse 'House origin must use HTTPS or local loopback HTTP'
79
- DOCKER_RUN=(docker run --rm --network host --user "$(id -u):$(id -g)" --mount "type=bind,src=$KIT_HOME,dst=/kit-home" --mount "type=bind,src=$WORKSPACE,dst=/agents/house" --env HOME=/kit-home --env HOUSE_KIT_HOME=/kit-home --env HOUSE_KIT_CONTAINER=1 --env "HOUSE_KIT_HOSTNAME=$(hostname)" "$IMAGE")
218
+ if ((FORWARDING == 0)); then
219
+ if [[ ! -f "$KIT_HOME/kit.json" ]]; then
220
+ printf '{"availability":"intermittent","execution_authority":"allow","migrators":[],"instances":[],"clients":[],"host":null,"skills":%s}\n' "$SKILLS" > "$KIT_HOME/kit.json"
221
+ elif grep -Eq '"skills"[[:space:]]*:' "$KIT_HOME/kit.json"; then
222
+ sed -E -i "s/(\"skills\"[[:space:]]*:[[:space:]]*)(true|false)/\\1$SKILLS/" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
223
+ else
224
+ sed -E -i "1s/^([[:space:]]*)\\{/\\1{\"skills\":$SKILLS,/" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
225
+ fi
226
+ grep -Eq "\"skills\"[[:space:]]*:[[:space:]]*$SKILLS" "$KIT_HOME/kit.json" || refuse 'kit.json could not be updated'
227
+ fi
228
+ DOCKER_RUN=(docker run --rm --network host --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")
80
229
 
81
230
  if docker container inspect "$NAME" >/dev/null 2>&1; then
82
- [[ "$(docker inspect --format '{{.Config.Image}}' "$NAME")" == "$IMAGE" ]] || refuse 'an installed Kit uses a different image; update it explicitly'
231
+ INSTALLED_IMAGE=$(docker inspect --format '{{.Config.Image}}' "$NAME")
232
+ ((FORWARDING == 0)) || [[ "$INSTALLED_IMAGE" == "$IMAGE" ]] || refuse 'an installed Kit uses a different image; rerun this bootstrap without arguments to update it'
83
233
  [[ "$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' "$NAME")" == unless-stopped ]] || refuse 'the installed Kit has a different lifecycle'
84
234
  [[ "$(docker inspect --format '{{len .Mounts}}' "$NAME")" == 2 ]] || refuse 'the installed Kit has unexpected mounts'
85
235
  [[ "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/kit-home"}}{{.Source}}{{end}}{{end}}' "$NAME")" == "$KIT_HOME" ]] || refuse 'the installed Kit uses another Kit home'
@@ -88,7 +238,45 @@ if docker container inspect "$NAME" >/dev/null 2>&1; then
88
238
  [[ "$(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
239
  [[ "$(docker inspect --format '{{index .Config.Labels "agentshouse.house"}}' "$NAME")" == "$HOUSE" ]] || refuse 'the installed Kit uses another House origin'
90
240
  [[ -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"
241
+ if ((FORWARDING)); then
242
+ if [[ "$FORWARDED" == kit && "${FORWARD[0]:-}" == login ]]; then
243
+ login_kit "${FORWARD[@]:1}"
244
+ exit 0
245
+ fi
246
+ PLACED=()
247
+ ENTRY=()
248
+ if [[ "$FORWARDED" == house ]]; then
249
+ HERE=$(pwd -P)
250
+ [[ "$HERE" == "$WORKSPACE" || "$HERE" == "$WORKSPACE"/* ]] || refuse "the current directory is outside the workspace $WORKSPACE"
251
+ PLACED=(--workdir "/agents/house${HERE#"$WORKSPACE"}")
252
+ ENTRY=(--entrypoint house)
253
+ fi
254
+ TERMINAL=()
255
+ if [[ -t 0 && -t 1 ]]; then TERMINAL=(-t); fi
256
+ if [[ -t 0 && ! -t 1 ]]; then
257
+ ECHOED=$(stty -g)
258
+ trap 'stty "$ECHOED"' EXIT
259
+ stty -echo
260
+ fi
261
+ if [[ "$(docker inspect --format '{{.State.Running}}' "$NAME")" == true ]]; then
262
+ docker exec -i "${TERMINAL[@]}" "${PLACED[@]}" "$NAME" "$FORWARDED" "${FORWARD[@]}"
263
+ else
264
+ "${DOCKER_RUN[@]:0:2}" -i "${TERMINAL[@]}" "${PLACED[@]}" "${ENTRY[@]}" "${DOCKER_RUN[@]:2}" "${FORWARD[@]}"
265
+ fi
266
+ exit
267
+ fi
268
+ if [[ "$INSTALLED_IMAGE" != "$IMAGE" ]]; then
269
+ docker pull --quiet --platform "linux/$ARCH" "$IMAGE" >/dev/null
270
+ if [[ "$(docker inspect --format '{{.State.Running}}' "$NAME")" == true ]]; then
271
+ docker exec "$NAME" kit resident drain
272
+ fi
273
+ docker rm -f "$NAME" >/dev/null
274
+ rm -f "$KIT_HOME/state/update-drain"
275
+ start_resident
276
+ printf 'House Kit updated for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
277
+ exit 0
278
+ fi
279
+ "${DOCKER_RUN[@]}" credential check
92
280
  if [[ "$(docker inspect --format '{{.State.Running}}' "$NAME")" == true ]]; then
93
281
  printf 'House Kit is already running for Environment %s.\n' "$(cat "$KIT_HOME/environment")"
94
282
  else
@@ -100,28 +288,15 @@ fi
100
288
 
101
289
  docker pull --quiet --platform "linux/$ARCH" "$IMAGE" >/dev/null
102
290
 
103
- if [[ ! -f "$KIT_HOME/kit.json" ]]; then
104
- printf '{"availability":"intermittent","execution_authority":"allow","migrators":[],"instances":[],"clients":[],"host":null}\n' > "$KIT_HOME/kit.json"
105
- fi
106
-
107
291
  if [[ -f "$KIT_HOME/credential" ]]; then
108
- "${DOCKER_RUN[@]}" credential check --house "$HOUSE"
292
+ "${DOCKER_RUN[@]}" credential check
109
293
  else
110
- if ((MANUAL)); then
111
- "${DOCKER_RUN[@]:0:2}" -i "${DOCKER_RUN[@]:2}" login --house "$HOUSE" --manual
112
- else
113
- command -v xdg-open >/dev/null || refuse 'no host browser opener; rerun with --manual'
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
122
- fi
294
+ LOGIN=()
295
+ if ((HOUSE_SELECTED)); then LOGIN+=(--house "$HOUSE"); fi
296
+ if ((MANUAL)); then LOGIN+=(--manual); fi
297
+ login_kit "${LOGIN[@]}"
123
298
  fi
124
299
 
125
- "${DOCKER_RUN[@]}" apply --house "$HOUSE"
126
- docker run -d --name "$NAME" --restart unless-stopped --user "$(id -u):$(id -g)" --mount "type=bind,src=$KIT_HOME,dst=/kit-home" --mount "type=bind,src=$WORKSPACE,dst=/agents/house" --label "agentshouse.house=$HOUSE" --env HOME=/kit-home --env HOUSE_KIT_HOME=/kit-home --env HOUSE_KIT_CONTAINER=1 "$IMAGE" resident --house "$HOUSE" >/dev/null
300
+ "${DOCKER_RUN[@]}" apply
301
+ start_resident
127
302
  printf 'House Kit connected for Environment %s.\n' "$(cat "$KIT_HOME/environment")"