abstractframework 0.11.3__tar.gz → 0.11.4__tar.gz

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 (203) hide show
  1. {abstractframework-0.11.3 → abstractframework-0.11.4}/CHANGELOG.md +18 -0
  2. {abstractframework-0.11.3/abstractframework.egg-info → abstractframework-0.11.4}/PKG-INFO +1 -1
  3. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework/__init__.py +1 -1
  4. {abstractframework-0.11.3 → abstractframework-0.11.4/abstractframework.egg-info}/PKG-INFO +1 -1
  5. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/api.md +2 -2
  6. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/install.md +16 -6
  7. {abstractframework-0.11.3 → abstractframework-0.11.4}/llms-full.txt +21 -11
  8. {abstractframework-0.11.3 → abstractframework-0.11.4}/llms.txt +1 -1
  9. {abstractframework-0.11.3 → abstractframework-0.11.4}/pyproject.toml +1 -1
  10. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/install.sh +112 -26
  11. abstractframework-0.11.4/tests/test_install_app_upgrade.py +304 -0
  12. abstractframework-0.11.3/tests/test_install_app_upgrade.py +0 -174
  13. {abstractframework-0.11.3 → abstractframework-0.11.4}/LICENSE +0 -0
  14. {abstractframework-0.11.3 → abstractframework-0.11.4}/MANIFEST.in +0 -0
  15. {abstractframework-0.11.3 → abstractframework-0.11.4}/README.md +0 -0
  16. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework/__main__.py +0 -0
  17. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework/cli.py +0 -0
  18. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework/install_manifest.py +0 -0
  19. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework/py.typed +0 -0
  20. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework.egg-info/SOURCES.txt +0 -0
  21. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework.egg-info/dependency_links.txt +0 -0
  22. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework.egg-info/entry_points.txt +0 -0
  23. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework.egg-info/requires.txt +0 -0
  24. {abstractframework-0.11.3 → abstractframework-0.11.4}/abstractframework.egg-info/top_level.txt +0 -0
  25. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/README.md +0 -0
  26. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0001-layered-architecture.md +0 -0
  27. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0002-effect-system-design.md +0 -0
  28. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0003-tool-system-architecture.md +0 -0
  29. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0004-observability-strategy.md +0 -0
  30. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0005-memory-architecture.md +0 -0
  31. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0006-durable-tool-execution.md +0 -0
  32. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0007-active-context-and-memory-provenance.md +0 -0
  33. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0008-token-terminology.md +0 -0
  34. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0009-connected-memory-recall-and-provenance.md +0 -0
  35. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0010-runtime-owned-node-traces.md +0 -0
  36. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0011-ledger-subscriptions-and-event-bridge.md +0 -0
  37. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0012-portable-workflowartifact.md +0 -0
  38. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0013-durable-run-controls-pause-resume-cancel.md +0 -0
  39. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0014-runtime-authority-timeouts.md +0 -0
  40. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0015-execution-targets-and-remote-tool-workers.md +0 -0
  41. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0016-tool-calling-pipeline-and-responsibility-boundaries.md +0 -0
  42. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0017-host-ui-events-and-durable-prompts.md +0 -0
  43. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0018-durable-run-gateway-and-remote-host-control-plane.md +0 -0
  44. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0019-testing-strategy-and-levels.md +0 -0
  45. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0020-agent-host-pool-and-orchestrator-placement.md +0 -0
  46. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0021-deployment-topologies-and-supported-scenarios.md +0 -0
  47. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0022-orchestrator-host-and-runtime-daemonization.md +0 -0
  48. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0023-file-attachment-path-resolution-and-authorization.md +0 -0
  49. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0024-attachment-placeholders-and-compaction-invariants.md +0 -0
  50. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0025-kg-entity-normalization-and-dedup.md +0 -0
  51. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0026-truncation-policy-and-contract.md +0 -0
  52. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0027-timeout-policy-and-contract.md +0 -0
  53. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0028-capabilities-plugins-and-library-framework-modes.md +0 -0
  54. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0029-permissive-dependency-and-licensing-policy.md +0 -0
  55. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0030-security-test-fixtures-and-isolation.md +0 -0
  56. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0031-workflow-llm-routing-overrides-provider-model-and-base-url.md +0 -0
  57. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0032-package-dependency-boundaries-and-gateway-first-apps.md +0 -0
  58. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0033-install-profiles-config-entrypoints-and-server-boundaries.md +0 -0
  59. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0034-framework-release-sequence-and-gates.md +0 -0
  60. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0035-capability-routing-defaults.md +0 -0
  61. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0036-artifact-descriptor-contract.md +0 -0
  62. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0037-hosted-file-source-contract-and-workspacepath-authority.md +0 -0
  63. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/0038-script-bootstrap-and-gateway-console-install.md +0 -0
  64. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/README.md +0 -0
  65. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/memory-recall-levels.md +0 -0
  66. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/001_music_as_capability_plugin_via_acestep_api.md +0 -0
  67. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/002_abstractmusic_inprocess_local_generation.md +0 -0
  68. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/003_abstractmusic_acestep_v15_backend_source_strategy.md +0 -0
  69. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/004_smartnote_thin_client_architecture.md +0 -0
  70. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/005_smartnote_artifact_first_cards.md +0 -0
  71. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/2026-02-21_gateway-first-assistant.md +0 -0
  72. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/2026-02-21_installer_manager_strategy.md +0 -0
  73. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/adr/reorg/2026-02-21_macos_installer_manager.md +0 -0
  74. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/agent-sessions.md +0 -0
  75. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/architecture.md +0 -0
  76. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/automations.md +0 -0
  77. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/claude/README.md +0 -0
  78. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/claude/abstractframework-fit.md +0 -0
  79. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/claude/claude-skills-overview.md +0 -0
  80. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/claude/claude-skills-sources.md +0 -0
  81. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/claude/claude-skills-top-20.md +0 -0
  82. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/comparisons/README.md +0 -0
  83. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/configuration.md +0 -0
  84. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/faq.md +0 -0
  85. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/getting-started.md +0 -0
  86. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/glossary.md +0 -0
  87. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/LANDING.md +0 -0
  88. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/README.md +0 -0
  89. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/agent-skills.md +0 -0
  90. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/agent-vs-llm.md +0 -0
  91. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/agora-workflow-agent.md +0 -0
  92. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/apple-local-gateway-flow.md +0 -0
  93. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/capability-plugins.md +0 -0
  94. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/capability-routing-defaults.md +0 -0
  95. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/deployment-iphone.md +0 -0
  96. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/deployment-topologies.md +0 -0
  97. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/deployment-web.md +0 -0
  98. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/email-integration.md +0 -0
  99. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/event-inbox-agent.md +0 -0
  100. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/flow-and-kg-memory.md +0 -0
  101. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/gateway-security.md +0 -0
  102. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/headless-swarm.md +0 -0
  103. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/process-manager-env-vars.md +0 -0
  104. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/prompt-caching.md +0 -0
  105. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/runtime-artifacts.md +0 -0
  106. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/runtime-scope.md +0 -0
  107. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/scheduled-workflows.md +0 -0
  108. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/summoned-entities.md +0 -0
  109. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/telegram-integration.md +0 -0
  110. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/guide/workflow-bundles.md +0 -0
  111. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/README.md +0 -0
  112. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/components.md +0 -0
  113. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/implementation-plan.md +0 -0
  114. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/operations-and-support.md +0 -0
  115. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/release-and-manifest.md +0 -0
  116. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/security-and-os-blocks.md +0 -0
  117. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/strategy.md +0 -0
  118. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/installers/user-journeys.md +0 -0
  119. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/prompts/agora-collaboration.md +0 -0
  120. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/README.md +0 -0
  121. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/email-inbox-agent.md +0 -0
  122. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/gateway-first-local-dev.md +0 -0
  123. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/offline-coding-assistant.md +0 -0
  124. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/phone-thin-client.md +0 -0
  125. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/specialized-agent-flow.md +0 -0
  126. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/telegram-permanent-contact.md +0 -0
  127. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/scenarios/workflow-bundle-lifecycle.md +0 -0
  128. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/README.md +0 -0
  129. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/abstractframework-agent-skills-fit.md +0 -0
  130. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/abstractframework-architecture-deep-dive.md +0 -0
  131. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/agent-skills-ecosystem-scan.md +0 -0
  132. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/agent-skills-ecosystem-sources.md +0 -0
  133. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/claude-agent-skills-overview.md +0 -0
  134. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/claude-agent-skills-sources.md +0 -0
  135. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/skills/claude-agent-skills-top-20.md +0 -0
  136. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/troubleshooting.md +0 -0
  137. {abstractframework-0.11.3 → abstractframework-0.11.4}/docs/workspace-scripts.md +0 -0
  138. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/af-local.sh +0 -0
  139. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/af.sh +0 -0
  140. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/agora_react_flow_smoke.py +0 -0
  141. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/assistant-local.sh +0 -0
  142. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/assistant.sh +0 -0
  143. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/build.sh +0 -0
  144. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/cache_probe_local_backends.py +0 -0
  145. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/cache_steer_repl.py +0 -0
  146. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/check_identity_sync.py +0 -0
  147. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/clone.sh +0 -0
  148. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/code-local.sh +0 -0
  149. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/code.sh +0 -0
  150. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/commit.sh +0 -0
  151. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/console-local.sh +0 -0
  152. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/console.sh +0 -0
  153. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/core_operator_drive.py +0 -0
  154. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/deps.sh +0 -0
  155. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/entity-local.sh +0 -0
  156. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/entity.sh +0 -0
  157. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/event_inbox_flow_smoke.py +0 -0
  158. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/flow-local.sh +0 -0
  159. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/flow.sh +0 -0
  160. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/gateway-flow-local.sh +0 -0
  161. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/gateway-flow.sh +0 -0
  162. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/gateway-local.sh +0 -0
  163. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/gateway.sh +0 -0
  164. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/gen_llms_full.py +0 -0
  165. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/headless_fleet_bridge.py +0 -0
  166. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/headless_fleet_demo.py +0 -0
  167. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/headless_steer_repl.py +0 -0
  168. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/af_inventory.py +0 -0
  169. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/af_stack.sh +0 -0
  170. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/af_supervisor.sh +0 -0
  171. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/apps_common.sh +0 -0
  172. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/build_macos_installer.sh +0 -0
  173. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/gateway_flags.sh +0 -0
  174. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/gateway_user_tokens.py +0 -0
  175. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/lib/repo_groups.sh +0 -0
  176. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/meet_castor.sh +0 -0
  177. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/observer-local.sh +0 -0
  178. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/observer.sh +0 -0
  179. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/plan_walkthrough.py +0 -0
  180. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/pull.sh +0 -0
  181. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/push.sh +0 -0
  182. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/spawn_demo_agent.sh +0 -0
  183. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/start-local.sh +0 -0
  184. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/start.sh +0 -0
  185. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/status.sh +0 -0
  186. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/steer_repl.py +0 -0
  187. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/tests/test_af_supervisor.sh +0 -0
  188. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/tests/test_install_user_path.sh +0 -0
  189. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/tests/test_inventory.sh +0 -0
  190. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/tests/test_repo_scripts.sh +0 -0
  191. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/uninstall.sh +0 -0
  192. {abstractframework-0.11.3 → abstractframework-0.11.4}/scripts/visit_resume_cache_probe.py +0 -0
  193. {abstractframework-0.11.3 → abstractframework-0.11.4}/setup.cfg +0 -0
  194. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_gateway_launch_flags.py +0 -0
  195. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_install_index_lag.py +0 -0
  196. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_install_macos_profile.py +0 -0
  197. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_install_profiles.py +0 -0
  198. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_install_ps1_gpu_stack.py +0 -0
  199. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_install_ps1_own_gateway.py +0 -0
  200. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_install_sh_gpu_stack.py +0 -0
  201. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_install_sh_gpu_twin.py +0 -0
  202. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_llms_full.py +0 -0
  203. {abstractframework-0.11.3 → abstractframework-0.11.4}/tests/test_uv_tool_install_atomicity.py +0 -0
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to AbstractFramework will be documented in this file.
4
4
 
5
+ ## [0.11.4] - 2026-10-17
6
+
7
+ Installer fix: upgrades keep the browser apps on the release. Package pins are unchanged from 0.11.3
8
+ (AbstractGateway 0.15.1 across the light, Apple and GPU profiles).
9
+
10
+ - Re-running `install.sh` or `install.ps1` brings every browser app the gateway has installed (Flow,
11
+ Code, Observer, Continuum, Entity) to this release's version in every case the step covers: it
12
+ starts once the gateway's boot is over, waits up to 90 s for an app the gateway is still starting,
13
+ and signs its `abstractgateway apps` calls with the data dir's token passed as a parameter, so an
14
+ `ABSTRACTGATEWAY_AUTH_TOKEN` set in your shell for another gateway no longer makes the step fail.
15
+ - A copy of an app running outside the gateway on the app's port no longer hides the gateway's own
16
+ install: the install is updated, the summary's Apps line names the outside copy (`RUNNING: a copy
17
+ started outside the gateway, <version> on port <port> (pid <pid>)`), and a copy not at this release's
18
+ version is listed in red with the pid to stop. See [Upgrade the apps](docs/install.md#upgrade-the-apps).
19
+ - Who is affected: anyone upgrading with the one-line installers (`curl -LsSf https://abstractframework.ai/install.sh | sh`,
20
+ `powershell -ExecutionPolicy ByPass -c "irm https://abstractframework.ai/install.ps1 | iex"`). A fresh
21
+ `pip install abstractframework==0.11.4` resolves the same packages as 0.11.3.
22
+
5
23
  ## [0.11.3] - 2026-10-17
6
24
 
7
25
  Pins **AbstractGateway 0.15.1** across the light, Apple and GPU profiles. Other package pins are unchanged.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractframework
3
- Version: 0.11.3
3
+ Version: 0.11.4
4
4
  Summary: Unified installer and documentation hub for the AbstractFramework ecosystem
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractframework.ai>
6
6
  License: MIT
@@ -10,7 +10,7 @@ Most implementation functionality still lives in component projects.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
- __version__ = "0.11.3"
13
+ __version__ = "0.11.4"
14
14
  __author__ = "Laurent-Philippe Albou"
15
15
  __license__ = "MIT"
16
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractframework
3
- Version: 0.11.3
3
+ Version: 0.11.4
4
4
  Summary: Unified installer and documentation hub for the AbstractFramework ecosystem
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractframework.ai>
6
6
  License: MIT
@@ -55,11 +55,11 @@ The response type returned by `llm.generate(...)`.
55
55
 
56
56
  ### `__version__`
57
57
 
58
- The meta-package version (`0.11.3` for this release).
58
+ The meta-package version (`0.11.4` for this release).
59
59
 
60
60
  ### `RELEASE_VERSIONS`
61
61
 
62
- Dictionary mapping each ecosystem package name to the pinned version for this release. In 0.11.3:
62
+ Dictionary mapping each ecosystem package name to the pinned version for this release. In 0.11.4:
63
63
  `abstractcore` 2.26.0, `abstractruntime` 0.10.2, `abstractagent` 0.3.19, `abstractgateway` 0.15.1,
64
64
  `abstractskill` 0.3.0, `abstractmemory` 0.3.0, `abstractsemantics` 0.0.5, `abstractvoice` 0.15.0, `abstractvision` 0.3.33,
65
65
  `abstractmusic` 0.1.16, `abstract3d` 0.3.2, `abstractassistant` 0.14.0.
@@ -360,11 +360,21 @@ installer keeps them on the release: on every install and upgrade, once the gate
360
360
  browser app the gateway has installed is brought to this release's version (`--print` lists the
361
361
  planned updates) through the gateway's own `abstractgateway apps update <app> --version <version>`,
362
362
  so the gateway's apps registry stays right and a running app restarts on the new version. It is a
363
- command-line call against the running gateway (signed in with `<data dir>/auth/bootstrap-admin-token`),
364
- so it works the same on a headless or terminal-only machine: no browser or web console is involved. The
365
- summary's **Apps** line lists each app's version; an app that could not be updated is listed in red
366
- with the command to retry, and the installer exits 1. A fresh install installs no app: the console's
367
- **Apps** page installs them.
363
+ command-line call against the running gateway, signed in with `<data dir>/auth/bootstrap-admin-token`
364
+ passed as a parameter (an `ABSTRACTGATEWAY_AUTH_TOKEN` in your shell, set for another gateway, is
365
+ not used), so it works the same on a headless or terminal-only machine: no browser or web console is
366
+ involved. The step starts only once the gateway's boot is over (`/api/health` no longer says
367
+ `"status": "starting"`) and waits, up to 90 s, for an app the gateway is still starting, so the
368
+ update restarts it on the new version. The summary's **Apps** line lists each app's version; an app
369
+ that could not be updated is listed in red with the command to retry, and the installer exits 1. A
370
+ fresh install installs no app: the console's **Apps** page installs them.
371
+
372
+ An app's port may be held by a copy the gateway did not start: a leftover of a gateway that died
373
+ hard, or an app run by hand with `npx`. The gateway lists that copy as *external* and cannot stop or
374
+ restart it, so the gateway's own install is updated and the **Apps** line says `RUNNING: a copy
375
+ started outside the gateway, <version> on port <port> (pid <pid>)`; when that copy is not at this
376
+ release's version, the summary shows it in red with the pid to stop (`kill <pid>`, then
377
+ `abstractgateway apps launch <app>`).
368
378
 
369
379
  When no gateway answers (`--no-start` while the gateway is stopped), the installer writes the
370
380
  release's versions to `<data dir>/apps-upgrade.pending` instead, and the gateway (0.11.1 and later)
@@ -944,7 +954,7 @@ Python 3.11 to 3.13), but it gets PyPI's CPU-only PyTorch and no llama.cpp: use
944
954
  installer, which adds PyTorch's CUDA build and llama.cpp's prebuilt GPU build
945
955
  ([GPU on Windows](#gpu-on-windows-nvidia)).
946
956
 
947
- `abstractframework` 0.11.3 pins `abstractgateway==0.15.1`, `abstractassistant==0.14.0`,
957
+ `abstractframework` 0.11.4 pins `abstractgateway==0.15.1`, `abstractassistant==0.14.0`,
948
958
  `abstractcore==2.26.0`, `AbstractRuntime==0.10.2`, `abstractagent==0.3.19`, `abstractskill==0.3.0`,
949
959
  `AbstractMemory==0.3.0`, `abstractsemantics==0.0.5`, `abstractvoice==0.15.0`,
950
960
  `abstractvision==0.3.33`, `abstractmusic==0.1.16` and `abstract3d==0.3.2`. The `apple` and `gpu` extras select
@@ -616,7 +616,7 @@ Notes for LLMs working in this repo:
616
616
  - [abstractframework/__init__.py](abstractframework/__init__.py): `RELEASE_VERSIONS`, `NPM_RELEASE_VERSIONS`, `CRATE_RELEASE_VERSIONS`, `get_release_profile()`, `print_status()`.
617
617
  - [docs/installers/install-manifest.json](docs/installers/install-manifest.json): Generated install manifest, schema v2 (pins, profiles, npm apps, `bootstrap` gateway pin/scripts/flags, console-first `post_install`).
618
618
  - [scripts/install.sh](scripts/install.sh) / [scripts/install.ps1](scripts/install.ps1): The bootstrap installers.
619
- - abstractframework 0.11.3 pins (PyPI, `==`): abstractgateway 0.15.1, abstractassistant 0.14.0, abstractcore 2.26.0, AbstractRuntime 0.10.2, abstractagent 0.3.19, abstractskill 0.3.0, AbstractMemory 0.3.0, abstractsemantics 0.0.5, abstractvoice 0.15.0, abstractvision 0.3.33, abstractmusic 0.1.16, abstract3d 0.3.2.
619
+ - abstractframework 0.11.4 pins (PyPI, `==`): abstractgateway 0.15.1, abstractassistant 0.14.0, abstractcore 2.26.0, AbstractRuntime 0.10.2, abstractagent 0.3.19, abstractskill 0.3.0, AbstractMemory 0.3.0, abstractsemantics 0.0.5, abstractvoice 0.15.0, abstractvision 0.3.33, abstractmusic 0.1.16, abstract3d 0.3.2.
620
620
  - Released with it: npm `@abstractframework/flow` 0.10.0, `code` 0.11.2, `observer` 0.8.0, `continuum` 0.7.0, `entity` 0.7.1 (opened through the gateway at `/apps/<app>/`, or run with `npx`); crates (`CRATE_RELEASE_VERSIONS`) `abstractgateway-console` 0.16.0 (built by the installer by default), `abstractcore-console` 0.8.0, `abstractcode` 0.10.0, `abstracttui` 0.6.0; images `ghcr.io/lpalbou/abstractgateway:0.15.1`, `ghcr.io/lpalbou/abstractcore-server:2.26.0`.
621
621
  - Profiles: light (remote-only), apple (`abstractframework[apple]`, macOS 14+ Apple Silicon), gpu (`abstractframework[gpu]`); Python 3.10-3.13 (F5-TTS voice cloning in apple/gpu needs 3.11+).
622
622
 
@@ -645,7 +645,7 @@ build-backend = "setuptools.build_meta"
645
645
 
646
646
  [project]
647
647
  name = "abstractframework"
648
- version = "0.11.3"
648
+ version = "0.11.4"
649
649
  description = "Unified installer and documentation hub for the AbstractFramework ecosystem"
650
650
  readme = "README.md"
651
651
  license = {text = "MIT"}
@@ -781,7 +781,7 @@ Most implementation functionality still lives in component projects.
781
781
 
782
782
  from __future__ import annotations
783
783
 
784
- __version__ = "0.11.3"
784
+ __version__ = "0.11.4"
785
785
  __author__ = "Laurent-Philippe Albou"
786
786
  __license__ = "MIT"
787
787
 
@@ -4112,11 +4112,21 @@ installer keeps them on the release: on every install and upgrade, once the gate
4112
4112
  browser app the gateway has installed is brought to this release's version (`--print` lists the
4113
4113
  planned updates) through the gateway's own `abstractgateway apps update <app> --version <version>`,
4114
4114
  so the gateway's apps registry stays right and a running app restarts on the new version. It is a
4115
- command-line call against the running gateway (signed in with `<data dir>/auth/bootstrap-admin-token`),
4116
- so it works the same on a headless or terminal-only machine: no browser or web console is involved. The
4117
- summary's **Apps** line lists each app's version; an app that could not be updated is listed in red
4118
- with the command to retry, and the installer exits 1. A fresh install installs no app: the console's
4119
- **Apps** page installs them.
4115
+ command-line call against the running gateway, signed in with `<data dir>/auth/bootstrap-admin-token`
4116
+ passed as a parameter (an `ABSTRACTGATEWAY_AUTH_TOKEN` in your shell, set for another gateway, is
4117
+ not used), so it works the same on a headless or terminal-only machine: no browser or web console is
4118
+ involved. The step starts only once the gateway's boot is over (`/api/health` no longer says
4119
+ `"status": "starting"`) and waits, up to 90 s, for an app the gateway is still starting, so the
4120
+ update restarts it on the new version. The summary's **Apps** line lists each app's version; an app
4121
+ that could not be updated is listed in red with the command to retry, and the installer exits 1. A
4122
+ fresh install installs no app: the console's **Apps** page installs them.
4123
+
4124
+ An app's port may be held by a copy the gateway did not start: a leftover of a gateway that died
4125
+ hard, or an app run by hand with `npx`. The gateway lists that copy as *external* and cannot stop or
4126
+ restart it, so the gateway's own install is updated and the **Apps** line says `RUNNING: a copy
4127
+ started outside the gateway, <version> on port <port> (pid <pid>)`; when that copy is not at this
4128
+ release's version, the summary shows it in red with the pid to stop (`kill <pid>`, then
4129
+ `abstractgateway apps launch <app>`).
4120
4130
 
4121
4131
  When no gateway answers (`--no-start` while the gateway is stopped), the installer writes the
4122
4132
  release's versions to `<data dir>/apps-upgrade.pending` instead, and the gateway (0.11.1 and later)
@@ -4696,7 +4706,7 @@ Python 3.11 to 3.13), but it gets PyPI's CPU-only PyTorch and no llama.cpp: use
4696
4706
  installer, which adds PyTorch's CUDA build and llama.cpp's prebuilt GPU build
4697
4707
  ([GPU on Windows](#gpu-on-windows-nvidia)).
4698
4708
 
4699
- `abstractframework` 0.11.3 pins `abstractgateway==0.15.1`, `abstractassistant==0.14.0`,
4709
+ `abstractframework` 0.11.4 pins `abstractgateway==0.15.1`, `abstractassistant==0.14.0`,
4700
4710
  `abstractcore==2.26.0`, `AbstractRuntime==0.10.2`, `abstractagent==0.3.19`, `abstractskill==0.3.0`,
4701
4711
  `AbstractMemory==0.3.0`, `abstractsemantics==0.0.5`, `abstractvoice==0.15.0`,
4702
4712
  `abstractvision==0.3.33`, `abstractmusic==0.1.16` and `abstract3d==0.3.2`. The `apple` and `gpu` extras select
@@ -6877,11 +6887,11 @@ The response type returned by `llm.generate(...)`.
6877
6887
 
6878
6888
  ### `__version__`
6879
6889
 
6880
- The meta-package version (`0.11.3` for this release).
6890
+ The meta-package version (`0.11.4` for this release).
6881
6891
 
6882
6892
  ### `RELEASE_VERSIONS`
6883
6893
 
6884
- Dictionary mapping each ecosystem package name to the pinned version for this release. In 0.11.3:
6894
+ Dictionary mapping each ecosystem package name to the pinned version for this release. In 0.11.4:
6885
6895
  `abstractcore` 2.26.0, `abstractruntime` 0.10.2, `abstractagent` 0.3.19, `abstractgateway` 0.15.1,
6886
6896
  `abstractskill` 0.3.0, `abstractmemory` 0.3.0, `abstractsemantics` 0.0.5, `abstractvoice` 0.15.0, `abstractvision` 0.3.33,
6887
6897
  `abstractmusic` 0.1.16, `abstract3d` 0.3.2, `abstractassistant` 0.14.0.
@@ -185,7 +185,7 @@ Notes for LLMs working in this repo:
185
185
  - [abstractframework/__init__.py](abstractframework/__init__.py): `RELEASE_VERSIONS`, `NPM_RELEASE_VERSIONS`, `CRATE_RELEASE_VERSIONS`, `get_release_profile()`, `print_status()`.
186
186
  - [docs/installers/install-manifest.json](docs/installers/install-manifest.json): Generated install manifest, schema v2 (pins, profiles, npm apps, `bootstrap` gateway pin/scripts/flags, console-first `post_install`).
187
187
  - [scripts/install.sh](scripts/install.sh) / [scripts/install.ps1](scripts/install.ps1): The bootstrap installers.
188
- - abstractframework 0.11.3 pins (PyPI, `==`): abstractgateway 0.15.1, abstractassistant 0.14.0, abstractcore 2.26.0, AbstractRuntime 0.10.2, abstractagent 0.3.19, abstractskill 0.3.0, AbstractMemory 0.3.0, abstractsemantics 0.0.5, abstractvoice 0.15.0, abstractvision 0.3.33, abstractmusic 0.1.16, abstract3d 0.3.2.
188
+ - abstractframework 0.11.4 pins (PyPI, `==`): abstractgateway 0.15.1, abstractassistant 0.14.0, abstractcore 2.26.0, AbstractRuntime 0.10.2, abstractagent 0.3.19, abstractskill 0.3.0, AbstractMemory 0.3.0, abstractsemantics 0.0.5, abstractvoice 0.15.0, abstractvision 0.3.33, abstractmusic 0.1.16, abstract3d 0.3.2.
189
189
  - Released with it: npm `@abstractframework/flow` 0.10.0, `code` 0.11.2, `observer` 0.8.0, `continuum` 0.7.0, `entity` 0.7.1 (opened through the gateway at `/apps/<app>/`, or run with `npx`); crates (`CRATE_RELEASE_VERSIONS`) `abstractgateway-console` 0.16.0 (built by the installer by default), `abstractcore-console` 0.8.0, `abstractcode` 0.10.0, `abstracttui` 0.6.0; images `ghcr.io/lpalbou/abstractgateway:0.15.1`, `ghcr.io/lpalbou/abstractcore-server:2.26.0`.
190
190
  - Profiles: light (remote-only), apple (`abstractframework[apple]`, macOS 14+ Apple Silicon), gpu (`abstractframework[gpu]`); Python 3.10-3.13 (F5-TTS voice cloning in apple/gpu needs 3.11+).
191
191
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "abstractframework"
7
- version = "0.11.3"
7
+ version = "0.11.4"
8
8
  description = "Unified installer and documentation hub for the AbstractFramework ecosystem"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -127,7 +127,7 @@ AF_GATEWAY_PIN_DEFAULT="0.15.1"
127
127
  # minus the gateway itself and the Assistant, a separate app). They go to `uv tool install` as
128
128
  # constraints, so an install or an upgrade lands on exactly the tested matrix, never on
129
129
  # whatever newer library satisfies the gateway's floors. test_inventory.sh fails on drift.
130
- AF_FRAMEWORK_VERSION="0.11.3"
130
+ AF_FRAMEWORK_VERSION="0.11.4"
131
131
  AF_PY_MATRIX="abstractcore==2.26.0 AbstractRuntime==0.10.2 abstractagent==0.3.19 abstractskill==0.3.0 AbstractMemory==0.3.0 abstractsemantics==0.0.5 abstractvoice==0.15.0 abstractvision==0.3.33 abstractmusic==0.1.16 abstract3d==0.3.2"
132
132
  AF_PYTHON="3.12"
133
133
  AF_NPM_APPS="@abstractframework/flow@0.10.0 @abstractframework/code@0.11.2 @abstractframework/observer@0.8.0 @abstractframework/continuum@0.7.0 @abstractframework/entity@0.7.1"
@@ -792,6 +792,17 @@ incomplete_add() {
792
792
  # fresh install installs none: the console's Apps page installs them, at these versions. With no
793
793
  # gateway answering (--no-start while it is stopped) the versions go to
794
794
  # <data dir>/apps-upgrade.pending, which the gateway applies at its next start.
795
+ # Three things a plain "update what the list shows" got wrong (root backlog 1026; a remote
796
+ # upgrade on 2026-10-17 moved the gateway and left Flow where it was, with nothing in red):
797
+ # - a gateway answers /api/health with "status": "starting" while it boots and starts its
798
+ # enabled apps: nothing here runs before gw_booted says the boot is over, and an app the
799
+ # gateway is still starting is waited for (af_apps_settled), so the update restarts it;
800
+ # - the shell's ABSTRACTGATEWAY_AUTH_TOKEN (set for another gateway, or stale) wins over the
801
+ # data dir's bootstrap token in `abstractgateway apps`: the token is passed as a parameter;
802
+ # - a copy of an app started outside the gateway (a leftover of a gateway that died hard, or
803
+ # `npx` by hand) holds the app's port: the gateway lists THAT copy as "external" and keeps
804
+ # its own install hidden behind it. The install is updated all the same, and the summary
805
+ # says in red which copy is the one running and how to stop it.
795
806
  af_app_pin() { # af_app_pin ID -> this release's version of that browser app; non-zero when none
796
807
  for _s in $AF_NPM_APPS; do
797
808
  _n="${_s#@abstractframework/}"
@@ -799,13 +810,55 @@ af_app_pin() { # af_app_pin ID -> this release's version of that browser app; n
799
810
  done
800
811
  return 1
801
812
  }
802
- af_apps_installed() { # -> "ID:VERSION" per app the running gateway installed; non-zero when unreadable
803
- _aj="$("$GW" apps list --json --no-latest --url "$BASE_URL" --data-dir "$DATA_DIR" 2>>"${LOG_FILE:-/dev/null}" </dev/null)" || return 1
813
+ gw_booted() { # gw_booted BODY: 0 when BODY is a gateway's /api/health answer and its boot is over
814
+ printf '%s' "$1" | grep -q '"abstractgateway"' || return 1
815
+ # Gateways 0.15 and later answer "status": "starting" while they load and start their apps.
816
+ printf '%s' "$1" | grep -Eq '"status": *"starting"' && return 1
817
+ return 0
818
+ }
819
+ af_apps_token() { # the data dir's admin token, for `abstractgateway apps` as a direct parameter
820
+ tr -d '\r\n' <"$DATA_DIR/auth/bootstrap-admin-token" 2>/dev/null || :
821
+ }
822
+ af_apps_installed() { # -> one "ID VERSION SOURCE STATUS EXTVERSION EXTPORT EXTPID" line per app ("-": none); non-zero when unreadable
823
+ set -- "$GW" apps list --json --no-latest --url "$BASE_URL" --data-dir "$DATA_DIR"
824
+ _tok="$(af_apps_token)"; [ -z "$_tok" ] || set -- "$@" --token "$_tok"
825
+ _aj=""; _try=0
826
+ until _aj="$("$@" 2>>"${LOG_FILE:-/dev/null}" </dev/null)"; do
827
+ _try=$((_try + 1)); [ "$_try" -lt 3 ] || return 1
828
+ sleep 2
829
+ done
804
830
  printf '%s' "$_aj" | "$APPS_PY" -c '
805
831
  import json, sys
806
832
  for a in json.load(sys.stdin).get("apps") or []:
807
- if a.get("version") and a.get("source") != "external":
808
- print("%s:%s" % (a["id"], a["version"]))'
833
+ ext = a.get("external") if isinstance(a.get("external"), dict) else None
834
+ # An "external" row describes the copy running outside the gateway; what the gateway
835
+ # itself installed is its managed_version (None when it installed nothing).
836
+ version = a.get("managed_version") if a.get("source") == "external" else a.get("version")
837
+ if not version and ext is None:
838
+ continue
839
+ row = [a.get("id"), version, a.get("source"), a.get("status"),
840
+ (ext or {}).get("version"), (ext or {}).get("port"), (ext or {}).get("pid")]
841
+ print(" ".join(str(v) if v not in (None, "") else "-" for v in row))'
842
+ }
843
+ AF_APPS_START_WAIT="${AF_APPS_START_WAIT:-90}" # seconds to wait for apps the gateway is starting
844
+ af_apps_settled() { # -> af_apps_installed's rows once no app of this release is still "starting"
845
+ _w=0
846
+ while :; do
847
+ _rows="$(af_apps_installed)" || return 1
848
+ _starting=""
849
+ _ifs="$IFS"; IFS="$AF_NL"
850
+ for _r in $_rows; do
851
+ IFS="$_ifs"; set -- $_r
852
+ [ "${4:-}" = starting ] && af_app_pin "$1" >/dev/null && _starting="$_starting $1"
853
+ done
854
+ IFS="$_ifs"
855
+ [ -n "$_starting" ] || break
856
+ # (this function runs in a command substitution: what it says goes to the terminal, not the rows)
857
+ [ "$_w" -lt "$AF_APPS_START_WAIT" ] || { warn "still starting after $AF_APPS_START_WAIT s:$_starting (updated as it is)" >&2; break; }
858
+ [ "$_w" = 0 ] && info "the gateway is still starting$_starting: waiting for it" >&2
859
+ sleep 2; _w=$((_w + 2))
860
+ done
861
+ printf '%s\n' "$_rows"
809
862
  }
810
863
  af_apps_marker() { # the pins the gateway applies at its next start (one "ID VERSION" per line)
811
864
  mkdir -p "$DATA_DIR" && : >"$DATA_DIR/apps-upgrade.pending.tmp" || return 1
@@ -814,12 +867,22 @@ af_apps_marker() { # the pins the gateway applies at its next start (one "ID VE
814
867
  done
815
868
  mv -f "$DATA_DIR/apps-upgrade.pending.tmp" "$DATA_DIR/apps-upgrade.pending"
816
869
  }
870
+ AF_NL='
871
+ '
872
+ af_rows_version() { # af_rows_version ROWS ID -> the VERSION field of ID's row ("" when none)
873
+ _want="$2"; _ifs2="$IFS"; IFS="$AF_NL"
874
+ for _b in $1; do
875
+ IFS="$_ifs2"; set -- $_b
876
+ [ "$1" = "$_want" ] && { printf '%s\n' "$2"; break; }
877
+ done
878
+ IFS="$_ifs2"
879
+ }
817
880
  APPS_LINES=""
818
881
  af_apps_step() { # af_apps_step UP (1 = a gateway answers at BASE_URL); sets APPS_LINES for the summary
819
- APPS_LINES=""
882
+ APPS_LINES=""; _up="$1"
820
883
  _pins=""; for _s in $AF_NPM_APPS; do _n="${_s#@abstractframework/}"; _pins="$_pins ${_n%@*} ${_n##*@},"; done
821
884
  _pins="${_pins# }"; _pins="${_pins%,}"
822
- if [ "$1" != 1 ]; then
885
+ if [ "$_up" != 1 ]; then
823
886
  if [ "$PRINT" = 1 ]; then
824
887
  info "would bring every browser app the gateway has installed to this release's version ($_pins), restarting the running ones:"
825
888
  info " $(show_cmd abstractgateway apps update "<app>" --version "<version>")"
@@ -836,27 +899,36 @@ af_apps_step() { # af_apps_step UP (1 = a gateway answers at BASE_URL); sets AP
836
899
  fi
837
900
  return 0
838
901
  fi
839
- if ! _rows="$(af_apps_installed)"; then
902
+ if ! _rows="$(af_apps_settled)"; then
840
903
  warn "could not read the gateway's apps (abstractgateway apps list; see ${LOG_FILE:-the output above})"
841
904
  [ "$PRINT" = 1 ] && return 0
842
- incomplete_add "browser apps" "their versions could not be read from the gateway; check with: abstractgateway apps list" fail
905
+ incomplete_add "browser apps" "their versions could not be read from the gateway; check with: abstractgateway apps list --url $BASE_URL --data-dir $DATA_DIR" fail
843
906
  APPS_LINES="unknown: abstractgateway apps list failed"
844
907
  return 0
845
908
  fi
846
- _before="$_rows"; _did=0
909
+ _before="$_rows"; _did=0; _any=0
910
+ _ifs="$IFS"; IFS="$AF_NL"
847
911
  for _r in $_rows; do
848
- _id="${_r%%:*}"; _ver="${_r#*:}"
912
+ IFS="$_ifs"; set -- $_r
913
+ _id="$1"; _ver="$2"; _xv="${5:-}"; _xp="${6:-}"
849
914
  _pin="$(af_app_pin "$_id")" || continue
850
- if [ "$_ver" = "$_pin" ]; then
915
+ _any=1
916
+ if [ "$_ver" = - ]; then
917
+ info "$_id: a copy started outside the gateway runs on port $_xp (version $_xv); the gateway installed none, so there is nothing to update"
918
+ elif [ "$_ver" = "$_pin" ]; then
851
919
  ok "$_id $_ver (this release's version)"
852
920
  elif [ "$PRINT" = 1 ]; then
853
921
  info "would update $_id $_ver -> $_pin (restarted if running): $(show_cmd abstractgateway apps update "$_id" --version "$_pin")"
854
922
  else
855
- RUN_SOFT=1 run "update the $_id app to $_pin" "$GW" apps update "$_id" --version "$_pin" --url "$BASE_URL" --data-dir "$DATA_DIR"
923
+ set -- "$GW" apps update "$_id" --version "$_pin" --url "$BASE_URL" --data-dir "$DATA_DIR"
924
+ RUN_SHOW="$(show_cmd abstractgateway apps update "$_id" --version "$_pin")"
925
+ _tok="$(af_apps_token)"; [ -z "$_tok" ] || set -- "$@" --token "$_tok"
926
+ RUN_SOFT=1 run "update the $_id app to $_pin" "$@"
856
927
  _did=1
857
928
  fi
858
929
  done
859
- [ -n "$_rows" ] || info "no browser app installed yet: the console's Apps page installs them ($_pins)"
930
+ IFS="$_ifs"
931
+ [ "$_any" = 1 ] || info "no browser app installed yet: the console's Apps page installs them ($_pins)"
860
932
  [ "$PRINT" = 1 ] && return 0
861
933
  # What the gateway reports now is what the summary says: a failed update is never silent.
862
934
  if [ "$_did" = 1 ] && ! _rows="$(af_apps_installed)"; then
@@ -864,25 +936,39 @@ af_apps_step() { # af_apps_step UP (1 = a gateway answers at BASE_URL); sets AP
864
936
  APPS_LINES="unknown: abstractgateway apps list failed after the update"
865
937
  return 0
866
938
  fi
939
+ _ifs="$IFS"; IFS="$AF_NL"
867
940
  for _r in $_rows; do
868
- _id="${_r%%:*}"; _ver="${_r#*:}"
941
+ IFS="$_ifs"; set -- $_r
942
+ _id="$1"; _ver="$2"; _src="${3:-}"; _xv="${5:-}"; _xp="${6:-}"; _xpid="${7:-}"
869
943
  _pin="$(af_app_pin "$_id")" || continue
870
- _old=""; for _b in $_before; do [ "${_b%%:*}" = "$_id" ] && _old="${_b#*:}"; done
871
- if [ "$_ver" != "$_pin" ]; then
944
+ _old="$(af_rows_version "$_before" "$_id")"
945
+ if [ "$_ver" = - ]; then
946
+ _line="$_id: not installed by the gateway; a copy started outside it runs on port $_xp ($_xv)"
947
+ elif [ "$_ver" != "$_pin" ]; then
872
948
  warn "the $_id app is still $_ver, not $_pin"
873
949
  incomplete_add "the $_id app" "still $_ver, not this release's $_pin; retry: abstractgateway apps update $_id --version $_pin" fail
874
- APPS_LINES="${APPS_LINES}$_id $_ver (NOT $_pin: update failed)
875
- "
950
+ _line="$_id $_ver (NOT $_pin: update failed)"
876
951
  elif [ -n "$_old" ] && [ "$_old" != "$_ver" ]; then
877
952
  ok "the $_id app is now $_ver"
878
- APPS_LINES="${APPS_LINES}$_id $_old -> $_ver
879
- "
953
+ _line="$_id $_old -> $_ver"
880
954
  else
881
- APPS_LINES="${APPS_LINES}$_id $_ver
882
- "
955
+ _line="$_id $_ver"
956
+ fi
957
+ if [ "$_src" = external ] && [ "$_ver" != - ]; then
958
+ # The gateway's install is at $_ver, but the copy on the port is not the gateway's:
959
+ # the gateway cannot restart it, so that copy is what people get until it is stopped.
960
+ _line="$_line; RUNNING: a copy started outside the gateway, $_xv on port $_xp (pid $_xpid)"
961
+ if [ "$_xv" != "$_pin" ]; then
962
+ warn "the $_id app that runs is a copy started outside the gateway ($_xv on port $_xp, pid $_xpid), not the gateway's $_ver"
963
+ incomplete_add "the $_id app" "what runs is a copy started outside the gateway ($_xv on port $_xp, pid $_xpid), not this release's $_pin; stop it (kill $_xpid), then: abstractgateway apps launch $_id" fail
964
+ else
965
+ info "$_id: the copy running on port $_xp was started outside the gateway (pid $_xpid); it is at $_xv too"
966
+ fi
883
967
  fi
968
+ APPS_LINES="${APPS_LINES}${_line}${AF_NL}"
884
969
  done
885
- [ -n "$_rows" ] || APPS_LINES="none installed (the console's Apps page installs them)"
970
+ IFS="$_ifs"
971
+ [ "$_any" = 1 ] || APPS_LINES="none installed (the console's Apps page installs them)"
886
972
  return 0
887
973
  }
888
974
  # <<< apps-upgrade
@@ -3064,7 +3150,7 @@ if [ "$NO_START" = 0 ]; then
3064
3150
  _svc_log="$HOME/Library/Logs/AbstractGateway"
3065
3151
  [ "$OS_ID" = macos ] || _svc_log="journalctl --user -u abstractgateway"
3066
3152
  _glog="$([ "$MODE" = service ] && echo "$_svc_log" || echo "$GATEWAY_LOG")"
3067
- until http_get "$BASE_URL/api/health" | grep -q '"abstractgateway"'; do
3153
+ until _hb="$(http_get "$BASE_URL/api/health")" && gw_booted "$_hb"; do
3068
3154
  _i=$((_i + 1))
3069
3155
  if [ "$MODE" = background ] && ! pid_alive; then
3070
3156
  tail -n 30 "$GATEWAY_LOG" >&2 || true
@@ -3121,7 +3207,7 @@ fi
3121
3207
  step "Browser apps (this release's versions)"
3122
3208
  APPS_PY="$TOOL_VENV/bin/python"; [ -x "$APPS_PY" ] || APPS_PY="${TOOL_VENV2:+$TOOL_VENV2/bin/python}"
3123
3209
  _apps_up=0
3124
- if [ -x "$GW" ] && [ -n "$APPS_PY" ] && [ -x "$APPS_PY" ] && http_get "$BASE_URL/api/health" | grep -q '"abstractgateway"'; then _apps_up=1; fi
3210
+ if [ -x "$GW" ] && [ -n "$APPS_PY" ] && [ -x "$APPS_PY" ] && gw_booted "$(http_get "$BASE_URL/api/health")"; then _apps_up=1; fi
3125
3211
  af_apps_step "$_apps_up"
3126
3212
 
3127
3213
  # ---------------------------------------------------------------------------