@aopslabs/aops 0.2.0

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 (171) hide show
  1. package/LICENSE +19 -0
  2. package/NOTICE +7 -0
  3. package/README.md +203 -0
  4. package/assets/agent-assets/core/SKILL.md +49 -0
  5. package/assets/agent-assets/core/references/agentspace/SKILL.md +78 -0
  6. package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +108 -0
  7. package/assets/agent-assets/core/references/chatv3/SKILL.md +48 -0
  8. package/assets/agent-assets/core/references/collaborative-work/SKILL.md +85 -0
  9. package/assets/agent-assets/core/references/discuss/SKILL.md +66 -0
  10. package/assets/agent-assets/core/references/docman/SKILL.md +69 -0
  11. package/assets/agent-assets/core/references/hosted-chat/SKILL.md +64 -0
  12. package/assets/agent-assets/core/references/mission/SKILL.md +54 -0
  13. package/assets/agent-assets/core/references/projectman/SKILL.md +86 -0
  14. package/assets/agent-assets/core/references/sys/SKILL.md +36 -0
  15. package/assets/agent-assets/core/references/view/SKILL.md +58 -0
  16. package/assets/agent-assets/core/references/working-disciplines/SKILL.md +69 -0
  17. package/assets/agent-assets/core/user-guides/agent-assets.md +81 -0
  18. package/assets/agent-assets/core/user-guides/agentspace.md +1098 -0
  19. package/assets/agent-assets/core/user-guides/aops-cli.md +1107 -0
  20. package/assets/agent-assets/core/user-guides/aops-system.md +63 -0
  21. package/assets/agent-assets/core/user-guides/chatv3.md +113 -0
  22. package/assets/agent-assets/core/user-guides/docman.md +162 -0
  23. package/assets/agent-assets/core/user-guides/projectman.md +212 -0
  24. package/assets/agent-assets/core/user-guides/sys.md +94 -0
  25. package/assets/agent-assets/core/user-guides/working-disciplines.md +588 -0
  26. package/assets/agent-assets/gateway/aops/SKILL.md +14 -0
  27. package/assets/r6-remote-session-baseline.json +19 -0
  28. package/assets/skills/aops-install/SKILL.md +231 -0
  29. package/assets/skills/aops-install/agents/openai.yaml +4 -0
  30. package/dist/commands/activity.js +352 -0
  31. package/dist/commands/agent-profile.js +653 -0
  32. package/dist/commands/agent.js +710 -0
  33. package/dist/commands/agents-md.js +125 -0
  34. package/dist/commands/api.js +84 -0
  35. package/dist/commands/archive.js +873 -0
  36. package/dist/commands/artifact.js +535 -0
  37. package/dist/commands/assets.js +1414 -0
  38. package/dist/commands/auth/device-login.js +1 -0
  39. package/dist/commands/auth/legacy-export.js +177 -0
  40. package/dist/commands/auth/login.js +426 -0
  41. package/dist/commands/chat.js +1363 -0
  42. package/dist/commands/chatv3.js +1684 -0
  43. package/dist/commands/checkpoint.js +549 -0
  44. package/dist/commands/commercial-artifact.js +475 -0
  45. package/dist/commands/commercial-license.js +594 -0
  46. package/dist/commands/community-auth.js +62 -0
  47. package/dist/commands/community-cockpit.js +185 -0
  48. package/dist/commands/community-console.js +109 -0
  49. package/dist/commands/community-doctor.js +335 -0
  50. package/dist/commands/community-server.js +2062 -0
  51. package/dist/commands/community-setup.js +284 -0
  52. package/dist/commands/discuss.js +1448 -0
  53. package/dist/commands/doc.js +5219 -0
  54. package/dist/commands/experience.js +922 -0
  55. package/dist/commands/host.js +1127 -0
  56. package/dist/commands/init.js +118 -0
  57. package/dist/commands/memory.js +3129 -0
  58. package/dist/commands/mission.js +562 -0
  59. package/dist/commands/official-catalog.js +134 -0
  60. package/dist/commands/plan.js +84 -0
  61. package/dist/commands/playbook.js +415 -0
  62. package/dist/commands/pm/context.js +6 -0
  63. package/dist/commands/pm/index.js +701 -0
  64. package/dist/commands/pm/projectman.js +6266 -0
  65. package/dist/commands/project.js +1080 -0
  66. package/dist/commands/prompt.js +1024 -0
  67. package/dist/commands/repo-sync.js +1907 -0
  68. package/dist/commands/resource.js +527 -0
  69. package/dist/commands/skill.js +1211 -0
  70. package/dist/commands/start-disciplines.js +510 -0
  71. package/dist/commands/start.js +1343 -0
  72. package/dist/commands/target.js +309 -0
  73. package/dist/commands/version.js +42 -0
  74. package/dist/commands/view.js +1852 -0
  75. package/dist/launchers/cockpit.js +28 -0
  76. package/dist/launchers/options.js +74 -0
  77. package/dist/launchers/server.js +41 -0
  78. package/dist/lib/agent-assets/envelope.js +83 -0
  79. package/dist/lib/agent-assets/gateway.js +15 -0
  80. package/dist/lib/agent-assets/guards.js +23 -0
  81. package/dist/lib/agent-assets/hosted-discovery.js +148 -0
  82. package/dist/lib/agent-assets/hosted-package-input.js +154 -0
  83. package/dist/lib/agent-assets/legacy-pointer-migration.js +677 -0
  84. package/dist/lib/agent-assets/native-fs.js +589 -0
  85. package/dist/lib/agent-assets/package-manifest.js +324 -0
  86. package/dist/lib/agent-assets/portable-path.js +67 -0
  87. package/dist/lib/agent-assets/release-input.js +177 -0
  88. package/dist/lib/agent-assets/roots.js +45 -0
  89. package/dist/lib/agent-assets/runtime-binding-reader.js +545 -0
  90. package/dist/lib/agent-assets/runtime-targets.js +50 -0
  91. package/dist/lib/agent-assets/store-reader.js +1212 -0
  92. package/dist/lib/agent-assets/store-types.js +1 -0
  93. package/dist/lib/agent-assets/store-writer.js +1484 -0
  94. package/dist/lib/agent-assets/types.js +1 -0
  95. package/dist/lib/agent-assets/unicode-case-folding-v15-1.generated.js +1548 -0
  96. package/dist/lib/commercial-final-readiness.js +504 -0
  97. package/dist/lib/commercial-lifecycle-smoke-isolation.js +236 -0
  98. package/dist/lib/commercial-managed-postgres-docker-adapter.js +274 -0
  99. package/dist/lib/commercial-setup-readiness-adapter.js +179 -0
  100. package/dist/lib/community-client-contract.js +164 -0
  101. package/dist/lib/community-cockpit-lifecycle.js +601 -0
  102. package/dist/lib/community-command-abort.js +59 -0
  103. package/dist/lib/community-diagnostic.js +237 -0
  104. package/dist/lib/community-docker-adapter.js +498 -0
  105. package/dist/lib/community-home.js +31 -0
  106. package/dist/lib/community-instance-contract.js +148 -0
  107. package/dist/lib/community-instance-layout.js +97 -0
  108. package/dist/lib/community-lifecycle.js +1631 -0
  109. package/dist/lib/community-migration-snapshot.js +770 -0
  110. package/dist/lib/community-native-application-recovery.js +425 -0
  111. package/dist/lib/community-native-child.js +240 -0
  112. package/dist/lib/community-native-database-recovery.js +456 -0
  113. package/dist/lib/community-native-lifecycle.js +2458 -0
  114. package/dist/lib/community-native-migration.js +339 -0
  115. package/dist/lib/community-native-postgres.js +596 -0
  116. package/dist/lib/community-operation-journal.js +773 -0
  117. package/dist/lib/community-operation-lock.js +596 -0
  118. package/dist/lib/community-release-resolver.js +291 -0
  119. package/dist/lib/community-release-verifier.js +475 -0
  120. package/dist/lib/community-repo-discovery.js +252 -0
  121. package/dist/lib/community-setup-server-env.js +203 -0
  122. package/dist/lib/external-url.js +110 -0
  123. package/dist/lib/official-catalog-gateway.js +108 -0
  124. package/dist/lib/official-catalog.js +364 -0
  125. package/dist/lib/server-bootstrap.js +240 -0
  126. package/dist/lib/setup-agent-assets-bridge.js +176 -0
  127. package/dist/lib/setup-agent-assets-release.js +52 -0
  128. package/dist/lib/setup-external-postgres.js +108 -0
  129. package/dist/lib/setup-init-orchestrator.js +990 -0
  130. package/dist/lib/setup-install-guide.js +52 -0
  131. package/dist/lib/setup-installer-release.js +47 -0
  132. package/dist/lib/setup-local-postgres.js +329 -0
  133. package/dist/lib/setup-official-catalog-bridge.js +148 -0
  134. package/dist/lib/setup-readiness.js +888 -0
  135. package/dist/lib/tui-launcher.js +59 -0
  136. package/dist/main.js +150 -0
  137. package/dist/seeds/agents-md.js +54 -0
  138. package/dist/utils/agent-gateway.js +275 -0
  139. package/dist/utils/agents-md.js +281 -0
  140. package/dist/utils/api.js +255 -0
  141. package/dist/utils/chatv3-session-store.js +185 -0
  142. package/dist/utils/command.js +67 -0
  143. package/dist/utils/community-host-runtime.js +376 -0
  144. package/dist/utils/config.js +1015 -0
  145. package/dist/utils/discussion-workspace.js +552 -0
  146. package/dist/utils/experience-workspace.js +326 -0
  147. package/dist/utils/guide-paths.js +67 -0
  148. package/dist/utils/hosted-sugar.js +56 -0
  149. package/dist/utils/hosted-workspace.js +229 -0
  150. package/dist/utils/memory-workspace.js +537 -0
  151. package/dist/utils/operator-runtime.js +199 -0
  152. package/dist/utils/password-crypto.js +39 -0
  153. package/dist/utils/playbook-workspace.js +479 -0
  154. package/dist/utils/project-context.js +255 -0
  155. package/dist/utils/prompts.js +70 -0
  156. package/dist/utils/refresh-race.js +28 -0
  157. package/dist/utils/repo-config.js +109 -0
  158. package/dist/utils/repo-first-projectman.js +194 -0
  159. package/dist/utils/repo-first-storage.js +13 -0
  160. package/dist/utils/repo-first-view.js +305 -0
  161. package/dist/utils/session-guidance.js +278 -0
  162. package/dist/utils/session-state.js +137 -0
  163. package/dist/utils/table.js +39 -0
  164. package/dist/utils/transient-fs.js +49 -0
  165. package/dist/utils/workspace-root.js +1 -0
  166. package/launchers/aops-cockpit.ps1 +15 -0
  167. package/launchers/aops-cockpit.sh +16 -0
  168. package/launchers/aops-server.ps1 +15 -0
  169. package/launchers/aops-server.sh +16 -0
  170. package/native/tui/win32-x64/aops-tui.exe +0 -0
  171. package/package.json +81 -0
@@ -0,0 +1,231 @@
1
+ ---
2
+ name: aops-install
3
+ description: Guide an AI agent through safe AOPS Community npm installation with an existing database, AOPS-managed Docker PostgreSQL, or detected local PostgreSQL; then verify migrations, Gateway assets, server health, and Cockpit. Use for install, initialize, configure, repair, verify, or setup explanation requests after installing @aopslabs/aops.
4
+ ---
5
+
6
+ # AOPS Community installation
7
+
8
+ Use the installed `aops` command as live truth. Run the relevant `--help` before any mutation; do not guess flags from this skill when the installed version differs.
9
+
10
+ ## Inspect first
11
+
12
+ If the operator starts with `aops setup ai`, treat its copy-ready prompt as the
13
+ handoff into this packaged skill. The prompt is only an entry point; this skill
14
+ and the installed CLI's live help remain the detailed authority.
15
+
16
+ Run mutation-free discovery:
17
+
18
+ ```sh
19
+ aops --version
20
+ aops setup init --yes --json
21
+ ```
22
+
23
+ This setup envelope already includes installation, PostgreSQL, host, and Gateway
24
+ readiness. Read its actions before choosing a path. Run `aops assets status` or
25
+ `aops server status` separately only when that check is action-required and more
26
+ detail is needed.
27
+
28
+ Never place any PostgreSQL URL, application password, path 3 administrator
29
+ password, AuthV2 password, admin key, or token in argv, logs, committed files,
30
+ or chat. Use AOPS masked prompts or the documented private process environment.
31
+
32
+ ## Route by need
33
+
34
+ | Need | Smallest surface |
35
+ | --- | --- |
36
+ | inspect choices and readiness | `aops setup init --yes --json` |
37
+ | give any terminal AI agent a safe setup handoff | `aops setup ai` |
38
+ | normal operator installation | `aops setup init` |
39
+ | use an existing database URL | path `1`, then `aops setup server-env` |
40
+ | let AOPS manage Docker PostgreSQL | path `2` |
41
+ | create AOPS DB in PostgreSQL on this computer | path `3` |
42
+ | connect only to an existing AOPS server | path `4` |
43
+ | inspect or repair Gateway assets | `aops assets --help` |
44
+ | operate an installed local server | `aops server --help` |
45
+
46
+ Load only the section needed for the selected path. The current nested `--help`
47
+ owns exact flags.
48
+
49
+ ## Normal interactive installation
50
+
51
+ Prefer the normal setup menu:
52
+
53
+ ```sh
54
+ aops setup init
55
+ ```
56
+
57
+ All local-server paths use the normal `default` instance, API port `5900`, and
58
+ independently supervised Cockpit port `5922`, verify
59
+ migrations, install the verified Gateway for registered runtimes, reconcile the inert signed
60
+ official catalog, and leave starter/demo user data untouched. Interactive
61
+ setup applies after collecting the selected path's required private inputs; it
62
+ does not ask redundant continue, asset-selection, or asset-confirmation
63
+ questions. It automatically installs or repairs the verified AOPS core and
64
+ gateway for every registered runtime. The core supplies a small neutral router,
65
+ rich on-demand mounted-domain user guides, and public-safe collaboration and
66
+ working-discipline references. Setup makes disciplines available but does not
67
+ select one. Additional signed catalog packages are imported as discoverable,
68
+ inert choices. Use `--agent-assets skip` or `--no-catalog`
69
+ only when the operator explicitly opts out.
70
+
71
+ Treat the connected database as migration truth. An empty AOPS schema starts
72
+ from migration zero, valid per-domain migration prefixes resume from the next
73
+ entry, and a current schema is verify-only. Do not use an older CLI, release,
74
+ or setup-audit version to decide which migration runs.
75
+
76
+ For automatic Docker PostgreSQL, the container port is loopback-only and dynamically assigned. A destructive reset removes only exact instance/root/secret label-verified resources:
77
+
78
+ ```sh
79
+ aops server reset --remove-managed-postgres --confirm-data-loss --confirm-instance default
80
+ aops setup init
81
+ ```
82
+
83
+ Global AOPS skills and pointers are shared installation assets and remain installed after server reset.
84
+
85
+ The default `trusted-local` server binds only to `127.0.0.1:5900`; it never
86
+ trusts LAN or Tailscale interfaces. AOPS Server on `5900` and Cockpit on `5922`
87
+ are independent services and neither redirects to the other. Community does
88
+ not provide an authenticated non-loopback listener. Use a separate HTTPS
89
+ `remote-session` target for South. When upgrading an old installation, repair
90
+ the private env explicitly with `aops setup server-env --auth trusted-local`;
91
+ the rewrite removes retired local-auth assignments without printing them.
92
+
93
+ ## Path safety notes
94
+
95
+ Git clone is a secondary development path. The optional application image is
96
+ built from the same exact public npm CLI/server closure and runs the normal
97
+ `aops server setup` lifecycle inside the container. It is a distribution path,
98
+ not a fifth interactive `setup init` path. Path `2` manages only its namespaced,
99
+ label-verified PostgreSQL resources; unrelated Docker resources remain
100
+ operator-owned.
101
+
102
+ For path `1`, PostgreSQL is operator-owned and may be local, remote, managed,
103
+ or separately containerized. Run interactive `aops setup init` and select path
104
+ `1`; it asks for the PostgreSQL URL using masked input, then immediately tests
105
+ the connection with TLS `require`. A saved URL is offered as a masked default
106
+ on retry and can be kept or replaced. The TLS-policy menu appears only when the
107
+ default encrypted connection fails. Use `verify-full` with a trusted CA and
108
+ matching hostname; use `disable` only when the operator explicitly accepts
109
+ unencrypted transport. For
110
+ non-interactive work, inject `AOPS_PG_URL` privately or prepare it with
111
+ `aops setup server-env`, then inspect `aops setup init --path 1
112
+ --postgres-tls <policy> --yes --json`.
113
+
114
+ For path `3`, prefer interactive setup. It probes loopback PostgreSQL, asks for
115
+ an existing administrator role/password through masked input, creates a new
116
+ dedicated login and database with a generated application password, stores only
117
+ the application URL in the private user server-env, and runs the normal external
118
+ migrations. The administrator password is never stored. If PostgreSQL is absent
119
+ or stopped, return the platform-specific install/start actions reported by
120
+ readiness; do not silently run an elevated package manager. Automation may use
121
+ the private `AOPS_LOCAL_POSTGRES_ADMIN_PASSWORD` environment variable.
122
+ `--local-postgres-admin-no-password` works only with PostgreSQL TCP trust auth;
123
+ it does not bypass authentication or make Linux peer/socket auth work over
124
+ loopback TCP. If the administrator password is unknown, stop and ask the
125
+ operator to configure one through their local PostgreSQL administration flow
126
+ (for example, interactive `sudo -u postgres psql` followed by `\password
127
+ postgres`) before retrying.
128
+
129
+ For path `4`, connect this CLI to an existing AOPS Server without installing or
130
+ operating a local server or PostgreSQL. The interactive wizard asks for the
131
+ endpoint and target name, checks the exact endpoint, persists and selects the
132
+ target, and then offers browser-approved device login when required.
133
+
134
+ External targets require HTTPS with `remote-session` and `system-ca`.
135
+ `authv2-jwt-session` remains a one-release input alias and canonicalizes to
136
+ `remote-session`. Plain HTTP is not a remote-session transport, including on
137
+ Tailscale.
138
+
139
+ Use the target commands when the operator wants explicit add/check/select
140
+ steps:
141
+
142
+ ```sh
143
+ aops target add --name remote --api-base-url https://aops.example.com \
144
+ --auth-provider remote-session --tls-policy system-ca --apply
145
+ aops target doctor remote --json
146
+ aops target use remote --apply
147
+ ```
148
+
149
+ Run `aops auth login --target remote`; it uses the browser-approved device
150
+ flow and forces a new remote session rather than accepting old local
151
+ credentials. Verify with
152
+ `aops auth status --target remote`; use normal
153
+ `aops auth logout --target remote` to revoke the remote session.
154
+ `--local-only` is an explicit fallback that clears only local credentials when
155
+ remote revocation is unavailable.
156
+
157
+ ## Apply explicitly in automation
158
+
159
+ Interactive `aops setup init` applies directly. For agents, CI, and scripts,
160
+ run the selected path's mutation-free readiness first and apply only after its
161
+ required actions and private inputs are understood:
162
+
163
+ ```sh
164
+ aops setup init --path 2 --yes --json
165
+ aops setup init --path 2 --plan-id sha256:<64-hex> --apply --yes --json
166
+
167
+ aops setup init --path 3 --yes --json
168
+ aops setup init --path 3 --plan-id sha256:<64-hex> --apply
169
+
170
+ aops setup init --path 4 --api-base-url https://aops.example.com \
171
+ --target-name remote --target-auth-provider remote-session \
172
+ --target-tls-policy system-ca --yes --json
173
+ aops setup init --path 4 --api-base-url https://aops.example.com \
174
+ --target-name remote --target-auth-provider remote-session \
175
+ --target-tls-policy system-ca --apply --yes --json
176
+ ```
177
+
178
+ For paths 1-3, read `installerPlan.planId` from the mutation-free preview and
179
+ pass that exact value to the apply command. A stale identity fails before any
180
+ setup mutation. Never invent or reuse a plan id from another machine, source,
181
+ path, or readiness snapshot.
182
+
183
+ All paths install the verified Gateway for registered runtimes. Local-server
184
+ paths also reconcile the inert signed official catalog. No path seeds
185
+ starter/demo user data. Use `--agent-assets skip` or `--no-catalog` only for an
186
+ explicit opt-out.
187
+
188
+ If Gateway assets need a separate action, install for every runtime registered by this CLI:
189
+
190
+ ```sh
191
+ aops assets install --target all --apply --json
192
+ ```
193
+
194
+ Use `--target codex`, `--target claude`, comma-separated values such as `--target codex,claude`, or repeat `--target` for an explicit subset. Do not use `both`; it is not a selector.
195
+
196
+ Do not supply a release directory in the normal npm flow. `--from-release` and `--agent-assets-release` are maintainer/offline recovery overrides only. Do not write runtime homes from npm `postinstall`; Gateway writes require the explicit guarded commands above.
197
+
198
+ ## Verify and hand off
199
+
200
+ ```sh
201
+ aops server start --json
202
+ aops server health --json
203
+ aops cockpit start --json
204
+ aops cockpit health --json
205
+ aops assets status --verify full --json
206
+ aops cockpit --no-open --json
207
+ ```
208
+
209
+ For path `4`, replace the local lifecycle checks with:
210
+
211
+ ```sh
212
+ aops target doctor <target-name> --json
213
+ aops auth status --target <target-name> --json
214
+ ```
215
+
216
+ For an operator who wants the server attached to a visible terminal with live
217
+ logs, use the installed package's `launchers/aops-server.sh` on macOS/Linux or
218
+ `launchers/aops-server.ps1` on Windows. It directly invokes the packaged Node
219
+ launcher and Ctrl+C stops that foreground server. The matching
220
+ `aops-cockpit.sh`/`.ps1` starts only the independent Cockpit process and prints
221
+ its URL; it never starts the server implicitly. Do not copy database secrets
222
+ into these scripts or their arguments.
223
+
224
+ Read and report the apply result's migration verification, then report the
225
+ selected path, server health, registered runtime binding states, and the
226
+ separate server and Cockpit URLs. `aops server stop` must not stop Cockpit;
227
+ `aops cockpit stop` must not stop the server. Never report success from process
228
+ exit alone when JSON says
229
+ action-required, conflict, or unhealthy.
230
+
231
+ When setup remains incomplete, preserve the exact safe next action from the CLI output. Ask the operator only for missing authority or private configuration; do not bypass ownership conflicts, TLS decisions, or unknown user-owned runtime files.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "AOPS Installation"
3
+ short_description: "Guide agents through safe AOPS installation"
4
+ default_prompt: "Use $aops-install to inspect and complete this AOPS Community installation safely."
@@ -0,0 +1,352 @@
1
+ import { Command } from 'commander';
2
+ import { logError, logSuccess } from '@aopslabs/xf-cli-ui';
3
+ import { applyCommonOptions, compactPayload, normalizeNonEmpty } from '../utils/command.js';
4
+ import { invokeHostedToolWithApiState, requireApiState, unwrapHostedToolResult, } from '../utils/agent-gateway.js';
5
+ import { preferProjectNameBinding, resolveOwnerScopeIdFromBinding, resolveOwnerScopeIdFromProjectRecord, resolveProjectBindingContext, } from '../utils/project-context.js';
6
+ import { buildHostedSugarEnvelope, buildOperatorCookbook, } from '../utils/hosted-sugar.js';
7
+ import { GUIDE_PATHS } from '../utils/guide-paths.js';
8
+ function isRecord(value) {
9
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
10
+ }
11
+ function unwrapResultData(result) {
12
+ if (isRecord(result) && Object.prototype.hasOwnProperty.call(result, 'data')) {
13
+ return result.data;
14
+ }
15
+ return result;
16
+ }
17
+ function toInteger(value, label) {
18
+ if (typeof value === 'number' && Number.isInteger(value))
19
+ return value;
20
+ const normalized = normalizeNonEmpty(value);
21
+ if (!normalized)
22
+ throw new Error(`${label} must be an integer.`);
23
+ const parsed = Number.parseInt(normalized, 10);
24
+ if (!Number.isInteger(parsed))
25
+ throw new Error(`${label} must be an integer.`);
26
+ return parsed;
27
+ }
28
+ function extractId(value) {
29
+ return normalizeNonEmpty(value);
30
+ }
31
+ function collectActivityArtifacts(result) {
32
+ const root = unwrapResultData(result) ?? (isRecord(result) ? result : {});
33
+ const activityItemId = extractId(root?.activityItemId) ?? extractId(root?.id);
34
+ return activityItemId ? { activityItemId } : undefined;
35
+ }
36
+ function jsonByteLength(value) {
37
+ try {
38
+ return Buffer.byteLength(JSON.stringify(value), 'utf8');
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
44
+ function summarizeText(value, maxLength = 240) {
45
+ const text = normalizeNonEmpty(value);
46
+ if (!text)
47
+ return undefined;
48
+ if (text.length <= maxLength)
49
+ return text;
50
+ return `${text.slice(0, maxLength - 3)}...`;
51
+ }
52
+ function summarizeUnknown(value) {
53
+ if (value === undefined)
54
+ return undefined;
55
+ if (isRecord(value)) {
56
+ const keys = Object.keys(value).sort();
57
+ return compactPayload({
58
+ kind: 'object',
59
+ keyCount: keys.length,
60
+ keys,
61
+ bytes: jsonByteLength(value),
62
+ });
63
+ }
64
+ if (Array.isArray(value)) {
65
+ return compactPayload({
66
+ kind: 'array',
67
+ length: value.length,
68
+ bytes: jsonByteLength(value),
69
+ });
70
+ }
71
+ return compactPayload({
72
+ kind: value === null ? 'null' : typeof value,
73
+ bytes: jsonByteLength(value),
74
+ preview: summarizeText(value, 80),
75
+ });
76
+ }
77
+ function summarizeRefs(value) {
78
+ if (value === undefined)
79
+ return undefined;
80
+ if (!Array.isArray(value))
81
+ return summarizeUnknown(value);
82
+ const types = Array.from(new Set(value
83
+ .map((entry) => (isRecord(entry) ? normalizeNonEmpty(entry.type) : undefined))
84
+ .filter((entry) => Boolean(entry)))).sort();
85
+ const preview = value.slice(0, 5).map((entry) => {
86
+ if (!isRecord(entry))
87
+ return entry;
88
+ return compactPayload({
89
+ type: normalizeNonEmpty(entry.type),
90
+ id: normalizeNonEmpty(entry.id),
91
+ label: summarizeText(entry.label, 80),
92
+ });
93
+ });
94
+ return compactPayload({
95
+ kind: 'array',
96
+ length: value.length,
97
+ types,
98
+ preview,
99
+ previewTruncated: value.length > preview.length ? true : undefined,
100
+ bytes: jsonByteLength(value),
101
+ });
102
+ }
103
+ function summarizeActivityRecord(value) {
104
+ if (!isRecord(value))
105
+ return value;
106
+ const summary = normalizeNonEmpty(value.summary);
107
+ const summaryPreview = summarizeText(summary);
108
+ return compactPayload({
109
+ id: normalizeNonEmpty(value.id),
110
+ scopeId: normalizeNonEmpty(value.scopeId),
111
+ projectId: normalizeNonEmpty(value.projectId),
112
+ sourceKind: normalizeNonEmpty(value.sourceKind),
113
+ sourceId: normalizeNonEmpty(value.sourceId),
114
+ action: normalizeNonEmpty(value.action),
115
+ status: normalizeNonEmpty(value.status),
116
+ summary: summaryPreview,
117
+ summaryBytes: summary ? Buffer.byteLength(summary, 'utf8') : undefined,
118
+ summaryTruncated: summary && summaryPreview !== summary ? true : undefined,
119
+ refsSummary: summarizeRefs(value.refs),
120
+ payloadSummary: summarizeUnknown(value.payload),
121
+ metaSummary: summarizeUnknown(value.meta),
122
+ createdAt: normalizeNonEmpty(value.createdAt),
123
+ updatedAt: normalizeNonEmpty(value.updatedAt),
124
+ });
125
+ }
126
+ function summarizeActivityListResult(result) {
127
+ if (Array.isArray(result))
128
+ return result.map(summarizeActivityRecord);
129
+ if (isRecord(result) && Array.isArray(result.data)) {
130
+ const data = result.data.map(summarizeActivityRecord);
131
+ return {
132
+ ...result,
133
+ data,
134
+ summary: {
135
+ ...(isRecord(result.summary) ? result.summary : {}),
136
+ mode: 'activity-list-summary',
137
+ count: data.length,
138
+ omitted: ['refs', 'payload', 'meta'],
139
+ fullRecordHint: 'Use `aops-cli activity get --id <activity-id> --json` without --summary for full refs/payload/meta.',
140
+ },
141
+ };
142
+ }
143
+ return summarizeActivityRecord(result);
144
+ }
145
+ function summarizeActivityGetResult(result) {
146
+ if (isRecord(result) && Object.prototype.hasOwnProperty.call(result, 'data')) {
147
+ return {
148
+ ...result,
149
+ data: summarizeActivityRecord(result.data),
150
+ summary: {
151
+ ...(isRecord(result.summary) ? result.summary : {}),
152
+ mode: 'activity-get-summary',
153
+ omitted: ['refs', 'payload', 'meta'],
154
+ fullRecordHint: 'Run without --summary for full refs/payload/meta.',
155
+ },
156
+ };
157
+ }
158
+ return summarizeActivityRecord(result);
159
+ }
160
+ function buildGatewayOptions(options, resolvedContext) {
161
+ return {
162
+ ...options,
163
+ ...preferProjectNameBinding(resolvedContext),
164
+ };
165
+ }
166
+ async function hydrateProjectContext(apiState, options, resolvedContext) {
167
+ const projectId = normalizeNonEmpty(resolvedContext.projectId);
168
+ if (!projectId)
169
+ return resolvedContext;
170
+ if (normalizeNonEmpty(options.scopeId))
171
+ return resolvedContext;
172
+ const payload = await invokeHostedToolWithApiState(apiState, {
173
+ ...buildGatewayOptions(options, resolvedContext),
174
+ toolId: 'agentspace.project.get-by-id',
175
+ input: { id: projectId },
176
+ });
177
+ const result = unwrapHostedToolResult(payload);
178
+ const project = unwrapResultData(result);
179
+ if (!isRecord(project))
180
+ return resolvedContext;
181
+ const scopeId = resolveOwnerScopeIdFromProjectRecord(project, resolvedContext.scopeId);
182
+ const projectName = normalizeNonEmpty(project.name) ?? resolvedContext.projectName;
183
+ return {
184
+ ...resolvedContext,
185
+ scopeId,
186
+ projectName,
187
+ };
188
+ }
189
+ async function resolveActivityContext(options, apiState) {
190
+ const resolved = await resolveProjectBindingContext(options, {
191
+ requireProject: false,
192
+ });
193
+ const scopeId = normalizeNonEmpty(options.scopeId) ?? resolveOwnerScopeIdFromBinding(resolved);
194
+ return hydrateProjectContext(apiState, options, {
195
+ ...resolved,
196
+ scopeId,
197
+ });
198
+ }
199
+ function buildResolvedContextRecord(context) {
200
+ return compactPayload({
201
+ repoRoot: context.repoRoot,
202
+ configPath: context.configPath,
203
+ configFound: context.configFound,
204
+ scopeId: context.scopeId,
205
+ projectId: context.projectId,
206
+ projectName: context.projectName,
207
+ });
208
+ }
209
+ const buildEnvelope = buildHostedSugarEnvelope;
210
+ function ensureActivityId(id, label = '--id') {
211
+ const resolved = normalizeNonEmpty(id);
212
+ if (!resolved)
213
+ throw new Error(`Provide ${label}.`);
214
+ return resolved;
215
+ }
216
+ export async function runActivityList(options = {}) {
217
+ try {
218
+ const apiState = await requireApiState(options);
219
+ if (!apiState)
220
+ return;
221
+ const resolvedContext = await resolveActivityContext(options, apiState);
222
+ const input = {
223
+ filter: compactPayload({
224
+ scopeId: normalizeNonEmpty(resolvedContext.scopeId),
225
+ scopeResolution: options.scopeResolution,
226
+ projectId: normalizeNonEmpty(options.filterProjectId),
227
+ sourceKind: normalizeNonEmpty(options.sourceKind),
228
+ sourceId: normalizeNonEmpty(options.sourceId),
229
+ action: normalizeNonEmpty(options.action),
230
+ status: normalizeNonEmpty(options.status),
231
+ }),
232
+ options: compactPayload({
233
+ limit: options.limit !== undefined ? toInteger(options.limit, '--limit') : undefined,
234
+ }),
235
+ };
236
+ const payload = await invokeHostedToolWithApiState(apiState, {
237
+ ...buildGatewayOptions(options, resolvedContext),
238
+ tenantId: options.tenantId,
239
+ locale: options.locale,
240
+ fallbackLocale: options.fallbackLocale,
241
+ timeoutMs: options.timeoutMs,
242
+ apiBaseUrl: options.apiBaseUrl,
243
+ accessToken: options.accessToken,
244
+ refreshToken: options.refreshToken,
245
+ toolId: 'agentspace.activity-item.list-activity-items',
246
+ input,
247
+ });
248
+ const result = unwrapHostedToolResult(payload);
249
+ const outputResult = options.summary ? summarizeActivityListResult(result) : result;
250
+ if (options.json) {
251
+ console.log(JSON.stringify(buildEnvelope({
252
+ command: 'activity.list',
253
+ toolId: 'agentspace.activity-item.list-activity-items',
254
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
255
+ input,
256
+ result: outputResult,
257
+ }), null, 2));
258
+ return;
259
+ }
260
+ logSuccess('Activity list loaded.');
261
+ console.log(JSON.stringify(outputResult, null, 2));
262
+ }
263
+ catch (error) {
264
+ logError(error instanceof Error ? error.message : String(error));
265
+ process.exitCode = 1;
266
+ }
267
+ }
268
+ export async function runActivityGet(options = {}) {
269
+ try {
270
+ const apiState = await requireApiState(options);
271
+ if (!apiState)
272
+ return;
273
+ const resolvedContext = await resolveActivityContext(options, apiState);
274
+ const id = ensureActivityId(options.id);
275
+ const input = { id };
276
+ const payload = await invokeHostedToolWithApiState(apiState, {
277
+ ...buildGatewayOptions(options, resolvedContext),
278
+ tenantId: options.tenantId,
279
+ locale: options.locale,
280
+ fallbackLocale: options.fallbackLocale,
281
+ timeoutMs: options.timeoutMs,
282
+ apiBaseUrl: options.apiBaseUrl,
283
+ accessToken: options.accessToken,
284
+ refreshToken: options.refreshToken,
285
+ toolId: 'agentspace.activity-item.get-by-id',
286
+ input,
287
+ });
288
+ const result = unwrapHostedToolResult(payload);
289
+ const outputResult = options.summary ? summarizeActivityGetResult(result) : result;
290
+ if (options.json) {
291
+ console.log(JSON.stringify(buildEnvelope({
292
+ command: 'activity.get',
293
+ toolId: 'agentspace.activity-item.get-by-id',
294
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
295
+ input,
296
+ artifacts: collectActivityArtifacts(result),
297
+ result: outputResult,
298
+ }), null, 2));
299
+ return;
300
+ }
301
+ logSuccess('Activity item loaded.');
302
+ console.log(JSON.stringify(outputResult, null, 2));
303
+ }
304
+ catch (error) {
305
+ logError(error instanceof Error ? error.message : String(error));
306
+ process.exitCode = 1;
307
+ }
308
+ }
309
+ function applyActivityContextOptions(cmd, params = {}) {
310
+ applyCommonOptions(cmd);
311
+ cmd.option('--project-id <id>', 'Project id used to resolve repo-bound activity ownership');
312
+ cmd.option('--project-name <name>', 'Project name used to resolve repo-bound activity ownership');
313
+ cmd.option('--scope-id <id>', 'Explicit scope id override for activity ownership');
314
+ if (params.withScopeResolution) {
315
+ cmd.option('--scope-resolution <mode>', 'Scope resolution policy: explicit or cascade');
316
+ }
317
+ return cmd;
318
+ }
319
+ export function makeActivityCommand() {
320
+ const cmd = new Command('activity').description('Agentspace activity ledger read sugar over the hosted AOPS gateway');
321
+ applyActivityContextOptions(cmd.command('list')
322
+ .description('List activity ledger items')
323
+ .option('--source-kind <kind>', 'Source kind filter: aops-cli, desktop, runner, system')
324
+ .option('--source-id <id>', 'Source id filter')
325
+ .option('--action <text>', 'Action filter')
326
+ .option('--status <status>', 'Status filter: success or error')
327
+ .option('--filter-project-id <id>', 'Activity projectId filter; separate from context --project-id')
328
+ .option('--limit <n>', 'Optional item limit')
329
+ .option('--summary', 'Print compact activity records and omit raw refs/payload/meta'), { withScopeResolution: true }).action(async (options) => {
330
+ await runActivityList(options);
331
+ });
332
+ applyActivityContextOptions(cmd.command('get')
333
+ .description('Get an activity ledger item by id')
334
+ .requiredOption('--id <id>', 'Activity item id')
335
+ .option('--summary', 'Omit raw refs/payload/meta and print compact size summaries')).action(async (options) => {
336
+ await runActivityGet(options);
337
+ });
338
+ cmd.addHelpText('after', buildOperatorCookbook({
339
+ examples: [
340
+ 'aops-cli activity list --summary --limit 20 --json',
341
+ 'aops-cli activity list --source-kind aops-cli --status success --summary --json',
342
+ 'aops-cli activity get --id <activity-id> --summary --json',
343
+ ],
344
+ guide: GUIDE_PATHS.agentspace,
345
+ notes: [
346
+ 'Activity commands are read-only and do not require --apply.',
347
+ 'Use --summary for inventories because activity refs, payload, and meta can be large.',
348
+ 'Use `aops-cli agent tools --domain agentspace --q activity --summary --json` for raw hosted operations not covered by this sugar.',
349
+ ],
350
+ }));
351
+ return cmd;
352
+ }