@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,1024 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Command } from 'commander';
3
+ import { logError, logSuccess } from '@aopslabs/xf-cli-ui';
4
+ import { applyCommonOptions, compactPayload, normalizeNonEmpty } from '../utils/command.js';
5
+ import { invokeHostedToolWithApiState, parseJsonInput, requireApiState, unwrapHostedToolResult, } from '../utils/agent-gateway.js';
6
+ import { resolveOwnerScopeIdFromBinding, resolveOwnerScopeIdFromProjectRecord, resolveProjectBindingContext, } from '../utils/project-context.js';
7
+ import { buildHostedSugarEnvelope, buildOperatorCookbook, ensureDestructiveWrite, ensureGuardedWrite, missingScopeIdMessage, resolveNextVersionNumber, } from '../utils/hosted-sugar.js';
8
+ import { GUIDE_PATHS } from '../utils/guide-paths.js';
9
+ function isRecord(value) {
10
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
11
+ }
12
+ function unwrapResultData(result) {
13
+ if (isRecord(result) && Object.prototype.hasOwnProperty.call(result, 'data')) {
14
+ return result.data;
15
+ }
16
+ return result;
17
+ }
18
+ function unwrapListItems(result) {
19
+ const data = unwrapResultData(result);
20
+ if (Array.isArray(data)) {
21
+ return data.filter((entry) => isRecord(entry));
22
+ }
23
+ if (isRecord(data) && Array.isArray(data.items)) {
24
+ return data.items.filter((entry) => isRecord(entry));
25
+ }
26
+ if (Array.isArray(result)) {
27
+ return result.filter((entry) => isRecord(entry));
28
+ }
29
+ return [];
30
+ }
31
+ function collectRepeatedOption(value, previous = []) {
32
+ const normalized = normalizeNonEmpty(value);
33
+ return normalized ? [...previous, normalized] : previous;
34
+ }
35
+ function toInteger(value, label) {
36
+ if (typeof value === 'number' && Number.isInteger(value))
37
+ return value;
38
+ const normalized = normalizeNonEmpty(value);
39
+ if (!normalized)
40
+ throw new Error(`${label} must be an integer.`);
41
+ const parsed = Number.parseInt(normalized, 10);
42
+ if (!Number.isInteger(parsed))
43
+ throw new Error(`${label} must be an integer.`);
44
+ return parsed;
45
+ }
46
+ function toStringArray(values) {
47
+ return Array.isArray(values)
48
+ ? values.map((entry) => normalizeNonEmpty(entry)).filter((entry) => Boolean(entry))
49
+ : [];
50
+ }
51
+ function normalizeTags(values) {
52
+ const seen = new Set();
53
+ const tags = [];
54
+ for (const value of toStringArray(values)) {
55
+ const normalized = value.toLowerCase();
56
+ if (seen.has(normalized))
57
+ continue;
58
+ seen.add(normalized);
59
+ tags.push(normalized);
60
+ }
61
+ return tags;
62
+ }
63
+ function recordMatchesTags(record, expectedTags) {
64
+ if (expectedTags.length === 0)
65
+ return true;
66
+ const actual = new Set(toStringArray(record.tags).map((tag) => tag.toLowerCase()));
67
+ return expectedTags.every((tag) => actual.has(tag));
68
+ }
69
+ function applyPromptTagFilter(result, expectedTags, limit) {
70
+ if (expectedTags.length === 0)
71
+ return result;
72
+ const filtered = unwrapListItems(result)
73
+ .filter((entry) => recordMatchesTags(entry, expectedTags))
74
+ .slice(0, limit);
75
+ if (isRecord(result) && Array.isArray(result.data)) {
76
+ return { ...result, data: filtered };
77
+ }
78
+ if (isRecord(result) && isRecord(result.data) && Array.isArray(result.data.items)) {
79
+ return { ...result, data: { ...result.data, items: filtered } };
80
+ }
81
+ if (Array.isArray(result))
82
+ return filtered;
83
+ return { ok: true, data: filtered };
84
+ }
85
+ function parseJsonSeed(input, label = '--input') {
86
+ const normalized = normalizeNonEmpty(input);
87
+ if (!normalized)
88
+ return {};
89
+ const parsed = parseJsonInput(normalized, label);
90
+ if (!isRecord(parsed))
91
+ throw new Error(`${label} must be a JSON object or @file.json object.`);
92
+ return parsed;
93
+ }
94
+ function parseUnknownJsonInput(input, label) {
95
+ const normalized = normalizeNonEmpty(input);
96
+ if (!normalized)
97
+ return undefined;
98
+ return parseJsonInput(normalized, label);
99
+ }
100
+ function readTextInput(input) {
101
+ if (typeof input !== 'string')
102
+ return undefined;
103
+ const trimmed = input.trim();
104
+ if (!trimmed)
105
+ return undefined;
106
+ if (trimmed.startsWith('@')) {
107
+ const filePath = trimmed.slice(1).trim();
108
+ if (!filePath)
109
+ throw new Error('Expected a file path after @.');
110
+ return readFileSync(filePath, 'utf8');
111
+ }
112
+ return input;
113
+ }
114
+ function resolveStringField(explicit, seed, key) {
115
+ return normalizeNonEmpty(explicit) ?? normalizeNonEmpty(seed[key]);
116
+ }
117
+ function resolveStringArrayField(explicit, seed, key) {
118
+ const explicitValues = toStringArray(explicit);
119
+ if (explicitValues.length > 0)
120
+ return explicitValues;
121
+ const seededValues = toStringArray(seed[key]);
122
+ return seededValues.length > 0 ? seededValues : undefined;
123
+ }
124
+ function resolveIntegerField(explicit, seed, key, label) {
125
+ if (explicit !== undefined && explicit !== null && explicit !== '')
126
+ return toInteger(explicit, label);
127
+ if (seed[key] !== undefined && seed[key] !== null && seed[key] !== '')
128
+ return toInteger(seed[key], label);
129
+ return undefined;
130
+ }
131
+ function resolveTextField(explicit, seed, key) {
132
+ const explicitValue = readTextInput(explicit);
133
+ if (explicitValue !== undefined)
134
+ return explicitValue;
135
+ return typeof seed[key] === 'string' ? seed[key] : undefined;
136
+ }
137
+ function resolveUnknownField(explicit, seed, key, label) {
138
+ const explicitValue = parseUnknownJsonInput(explicit, label);
139
+ if (explicitValue !== undefined)
140
+ return explicitValue;
141
+ return seed[key];
142
+ }
143
+ function extractId(value) {
144
+ return normalizeNonEmpty(value);
145
+ }
146
+ function collectPromptArtifacts(result) {
147
+ const root = unwrapResultData(result) ?? (isRecord(result) ? result : {});
148
+ const artifacts = {};
149
+ const push = (key, value) => {
150
+ const normalized = extractId(value);
151
+ if (normalized)
152
+ artifacts[key] = normalized;
153
+ };
154
+ push('promptId', root?.promptId);
155
+ if (!artifacts.promptId && !normalizeNonEmpty(root.promptId) && !normalizeNonEmpty(root.content)) {
156
+ push('promptId', root?.id);
157
+ }
158
+ push('currentVersionId', root?.currentVersionId);
159
+ push('promptVersionId', root?.promptVersionId);
160
+ if (!artifacts.promptVersionId && (normalizeNonEmpty(root.promptId) || normalizeNonEmpty(root.content))) {
161
+ push('promptVersionId', root?.id);
162
+ }
163
+ return Object.keys(artifacts).length > 0 ? artifacts : undefined;
164
+ }
165
+ function summarizeContent(value) {
166
+ const content = normalizeNonEmpty(value);
167
+ if (!content)
168
+ return undefined;
169
+ return compactPayload({
170
+ omitted: true,
171
+ bytes: Buffer.byteLength(content, 'utf8'),
172
+ lines: content.split(/\r\n|\r|\n/).length,
173
+ });
174
+ }
175
+ function summarizePromptVersionRecord(value) {
176
+ if (!isRecord(value))
177
+ return value;
178
+ const { content, ...rest } = value;
179
+ return compactPayload({
180
+ ...rest,
181
+ contentSummary: summarizeContent(content),
182
+ });
183
+ }
184
+ function summarizePromptCurrentResult(result) {
185
+ if (!isRecord(result))
186
+ return result;
187
+ return compactPayload({
188
+ ...result,
189
+ currentVersion: summarizePromptVersionRecord(result.currentVersion),
190
+ summary: {
191
+ mode: 'prompt-current-summary',
192
+ omitted: ['currentVersion.content'],
193
+ fullRecordHint: 'Use `aops-cli prompt current --id <prompt-id> --json` for full content.',
194
+ },
195
+ });
196
+ }
197
+ function summarizePromptInspectResult(result) {
198
+ if (!isRecord(result))
199
+ return result;
200
+ const versions = Array.isArray(result.versions)
201
+ ? result.versions.map(summarizePromptVersionRecord)
202
+ : result.versions;
203
+ return compactPayload({
204
+ ...result,
205
+ versions,
206
+ currentVersion: summarizePromptVersionRecord(result.currentVersion),
207
+ summary: {
208
+ ...(isRecord(result.summary) ? result.summary : {}),
209
+ mode: 'prompt-inspect-summary',
210
+ omitted: ['versions[].content', 'currentVersion.content'],
211
+ fullRecordHint: 'Use `aops-cli prompt inspect --id <prompt-id> --json` for full content.',
212
+ },
213
+ });
214
+ }
215
+ function summarizePromptVersionListResult(result) {
216
+ if (Array.isArray(result))
217
+ return result.map(summarizePromptVersionRecord);
218
+ if (!isRecord(result))
219
+ return result;
220
+ const data = Array.isArray(result.data)
221
+ ? result.data.map(summarizePromptVersionRecord)
222
+ : result.data;
223
+ const items = Array.isArray(result.items)
224
+ ? result.items.map(summarizePromptVersionRecord)
225
+ : result.items;
226
+ return compactPayload({
227
+ ...result,
228
+ data,
229
+ items,
230
+ summary: {
231
+ ...(isRecord(result.summary) ? result.summary : {}),
232
+ mode: 'prompt-version-list-summary',
233
+ omitted: ['data[].content', 'items[].content'],
234
+ fullRecordHint: 'Use `aops-cli prompt version list --prompt-id <prompt-id> --json` for full content.',
235
+ },
236
+ });
237
+ }
238
+ function buildGatewayOptions(options, resolvedContext) {
239
+ return {
240
+ ...options,
241
+ projectId: normalizeNonEmpty(options.projectId) ?? normalizeNonEmpty(resolvedContext.projectId),
242
+ projectName: normalizeNonEmpty(options.projectName) ?? normalizeNonEmpty(resolvedContext.projectName),
243
+ };
244
+ }
245
+ async function hydrateProjectContext(apiState, options, resolvedContext) {
246
+ const projectId = normalizeNonEmpty(resolvedContext.projectId);
247
+ if (!projectId)
248
+ return resolvedContext;
249
+ if (normalizeNonEmpty(options.scopeId)) {
250
+ return resolvedContext;
251
+ }
252
+ const payload = await invokeHostedToolWithApiState(apiState, {
253
+ ...buildGatewayOptions(options, resolvedContext),
254
+ toolId: 'agentspace.project.get-by-id',
255
+ input: { id: projectId },
256
+ });
257
+ const result = unwrapHostedToolResult(payload);
258
+ const project = unwrapResultData(result);
259
+ if (!isRecord(project))
260
+ return resolvedContext;
261
+ const scopeId = resolveOwnerScopeIdFromProjectRecord(project, resolvedContext.scopeId);
262
+ const projectName = normalizeNonEmpty(project.name) ?? resolvedContext.projectName;
263
+ return {
264
+ ...resolvedContext,
265
+ scopeId,
266
+ projectName,
267
+ };
268
+ }
269
+ async function resolvePromptContext(options, apiState) {
270
+ const resolved = await resolveProjectBindingContext(options, {
271
+ requireProject: false,
272
+ });
273
+ const scopeId = normalizeNonEmpty(options.scopeId) ?? resolveOwnerScopeIdFromBinding(resolved);
274
+ return hydrateProjectContext(apiState, options, {
275
+ ...resolved,
276
+ scopeId,
277
+ });
278
+ }
279
+ function buildResolvedContextRecord(context) {
280
+ return compactPayload({
281
+ repoRoot: context.repoRoot,
282
+ configPath: context.configPath,
283
+ configFound: context.configFound,
284
+ scopeId: context.scopeId,
285
+ projectId: context.projectId,
286
+ projectName: context.projectName,
287
+ });
288
+ }
289
+ const buildEnvelope = buildHostedSugarEnvelope;
290
+ function ensurePromptId(id, label = '--id') {
291
+ const resolved = normalizeNonEmpty(id);
292
+ if (!resolved)
293
+ throw new Error(`Provide ${label}.`);
294
+ return resolved;
295
+ }
296
+ function requireScopeId(context, seed) {
297
+ const scopeId = normalizeNonEmpty(context.scopeId) ?? normalizeNonEmpty(seed.scopeId);
298
+ if (!scopeId) {
299
+ throw new Error(missingScopeIdMessage('Prompt create'));
300
+ }
301
+ return scopeId;
302
+ }
303
+ function requireProjectId(options, context, seed) {
304
+ const projectId = normalizeNonEmpty(options.projectId) ??
305
+ normalizeNonEmpty(context.projectId) ??
306
+ normalizeNonEmpty(seed.projectId);
307
+ if (!projectId) {
308
+ throw new Error('Prompt version commands require repo-bound project context or --project-id.');
309
+ }
310
+ return projectId;
311
+ }
312
+ async function invokePromptTool(apiState, options, resolvedContext, params) {
313
+ ensureGuardedWrite(options, 'This command mutates hosted prompt state.');
314
+ const payload = await invokeHostedToolWithApiState(apiState, {
315
+ ...buildGatewayOptions(options, resolvedContext),
316
+ tenantId: options.tenantId,
317
+ locale: options.locale,
318
+ fallbackLocale: options.fallbackLocale,
319
+ timeoutMs: options.timeoutMs,
320
+ apiBaseUrl: options.apiBaseUrl,
321
+ accessToken: options.accessToken,
322
+ refreshToken: options.refreshToken,
323
+ toolId: params.toolId,
324
+ input: params.input,
325
+ preview: options.preview,
326
+ apply: options.apply,
327
+ confirm: options.confirm,
328
+ idempotencyKey: options.idempotencyKey,
329
+ });
330
+ const result = unwrapHostedToolResult(payload);
331
+ if (options.json) {
332
+ console.log(JSON.stringify(buildEnvelope({
333
+ command: params.command,
334
+ toolId: params.toolId,
335
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
336
+ input: params.input,
337
+ artifacts: collectPromptArtifacts(result),
338
+ result,
339
+ }), null, 2));
340
+ return;
341
+ }
342
+ logSuccess(params.successText);
343
+ console.log(JSON.stringify(result, null, 2));
344
+ }
345
+ export async function runPromptList(options = {}) {
346
+ try {
347
+ const apiState = await requireApiState(options);
348
+ if (!apiState)
349
+ return;
350
+ const resolvedContext = await resolvePromptContext(options, apiState);
351
+ const tags = normalizeTags(options.tag);
352
+ const limit = options.limit !== undefined ? toInteger(options.limit, '--limit') : undefined;
353
+ const input = {
354
+ filter: compactPayload({
355
+ scopeId: normalizeNonEmpty(resolvedContext.scopeId),
356
+ scopeResolution: options.scopeResolution,
357
+ name: normalizeNonEmpty(options.name),
358
+ status: normalizeNonEmpty(options.status),
359
+ tags: options.tag && options.tag.length > 0 ? options.tag : undefined,
360
+ }),
361
+ options: compactPayload({
362
+ limit,
363
+ }),
364
+ };
365
+ const payload = await invokeHostedToolWithApiState(apiState, {
366
+ ...buildGatewayOptions(options, resolvedContext),
367
+ tenantId: options.tenantId,
368
+ locale: options.locale,
369
+ fallbackLocale: options.fallbackLocale,
370
+ timeoutMs: options.timeoutMs,
371
+ apiBaseUrl: options.apiBaseUrl,
372
+ accessToken: options.accessToken,
373
+ refreshToken: options.refreshToken,
374
+ toolId: 'agentspace.prompt.list-prompts',
375
+ input,
376
+ });
377
+ let result = unwrapHostedToolResult(payload);
378
+ if (tags.length > 0 && unwrapListItems(result).length === 0) {
379
+ const fallbackInput = {
380
+ filter: compactPayload({
381
+ scopeId: normalizeNonEmpty(resolvedContext.scopeId),
382
+ scopeResolution: options.scopeResolution,
383
+ name: normalizeNonEmpty(options.name),
384
+ status: normalizeNonEmpty(options.status),
385
+ }),
386
+ };
387
+ const fallbackPayload = await invokeHostedToolWithApiState(apiState, {
388
+ ...buildGatewayOptions(options, resolvedContext),
389
+ tenantId: options.tenantId,
390
+ locale: options.locale,
391
+ fallbackLocale: options.fallbackLocale,
392
+ timeoutMs: options.timeoutMs,
393
+ apiBaseUrl: options.apiBaseUrl,
394
+ accessToken: options.accessToken,
395
+ refreshToken: options.refreshToken,
396
+ toolId: 'agentspace.prompt.list-prompts',
397
+ input: fallbackInput,
398
+ });
399
+ result = applyPromptTagFilter(unwrapHostedToolResult(fallbackPayload), tags, limit);
400
+ }
401
+ if (options.json) {
402
+ console.log(JSON.stringify(buildEnvelope({
403
+ command: 'prompt.list',
404
+ toolId: 'agentspace.prompt.list-prompts',
405
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
406
+ input,
407
+ result,
408
+ }), null, 2));
409
+ return;
410
+ }
411
+ logSuccess('Prompt list loaded.');
412
+ console.log(JSON.stringify(result, null, 2));
413
+ }
414
+ catch (error) {
415
+ logError(error instanceof Error ? error.message : String(error));
416
+ process.exitCode = 1;
417
+ }
418
+ }
419
+ export async function runPromptGet(options = {}) {
420
+ try {
421
+ const apiState = await requireApiState(options);
422
+ if (!apiState)
423
+ return;
424
+ const resolvedContext = await resolvePromptContext(options, apiState);
425
+ const id = ensurePromptId(options.id);
426
+ const input = { id };
427
+ const payload = await invokeHostedToolWithApiState(apiState, {
428
+ ...buildGatewayOptions(options, resolvedContext),
429
+ tenantId: options.tenantId,
430
+ locale: options.locale,
431
+ fallbackLocale: options.fallbackLocale,
432
+ timeoutMs: options.timeoutMs,
433
+ apiBaseUrl: options.apiBaseUrl,
434
+ accessToken: options.accessToken,
435
+ refreshToken: options.refreshToken,
436
+ toolId: 'agentspace.prompt.get-prompt',
437
+ input,
438
+ });
439
+ const result = unwrapHostedToolResult(payload);
440
+ if (options.json) {
441
+ console.log(JSON.stringify(buildEnvelope({
442
+ command: 'prompt.get',
443
+ toolId: 'agentspace.prompt.get-prompt',
444
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
445
+ input,
446
+ artifacts: collectPromptArtifacts(result),
447
+ result,
448
+ }), null, 2));
449
+ return;
450
+ }
451
+ logSuccess('Prompt loaded.');
452
+ console.log(JSON.stringify(result, null, 2));
453
+ }
454
+ catch (error) {
455
+ logError(error instanceof Error ? error.message : String(error));
456
+ process.exitCode = 1;
457
+ }
458
+ }
459
+ export async function runPromptCreate(options = {}) {
460
+ try {
461
+ const apiState = await requireApiState(options);
462
+ if (!apiState)
463
+ return;
464
+ const resolvedContext = await resolvePromptContext(options, apiState);
465
+ const seed = parseJsonSeed(options.input);
466
+ const name = resolveStringField(options.name, seed, 'name');
467
+ if (!name)
468
+ throw new Error('Prompt create requires --name or input.name.');
469
+ const input = {
470
+ data: compactPayload({
471
+ scopeId: requireScopeId(resolvedContext, seed),
472
+ name,
473
+ description: resolveStringField(options.description, seed, 'description'),
474
+ tags: resolveStringArrayField(options.tag, seed, 'tags'),
475
+ status: resolveStringField(options.status, seed, 'status') ?? 'draft',
476
+ }),
477
+ };
478
+ await invokePromptTool(apiState, options, resolvedContext, {
479
+ command: 'prompt.create',
480
+ toolId: 'agentspace.prompt.create',
481
+ input,
482
+ successText: 'Prompt created.',
483
+ });
484
+ }
485
+ catch (error) {
486
+ logError(error instanceof Error ? error.message : String(error));
487
+ process.exitCode = 1;
488
+ }
489
+ }
490
+ export async function runPromptUpdate(options = {}) {
491
+ try {
492
+ const apiState = await requireApiState(options);
493
+ if (!apiState)
494
+ return;
495
+ const resolvedContext = await resolvePromptContext(options, apiState);
496
+ const seed = parseJsonSeed(options.input);
497
+ const id = ensurePromptId(resolveStringField(options.id, seed, 'id'));
498
+ const patch = compactPayload({
499
+ name: resolveStringField(options.name, seed, 'name'),
500
+ description: resolveStringField(options.description, seed, 'description'),
501
+ status: resolveStringField(options.status, seed, 'status'),
502
+ tags: resolveStringArrayField(options.tag, seed, 'tags'),
503
+ currentVersionId: resolveStringField(options.currentVersionId, seed, 'currentVersionId'),
504
+ });
505
+ if (Object.keys(patch).length === 0) {
506
+ throw new Error('Provide at least one prompt field to update.');
507
+ }
508
+ const input = { id, patch };
509
+ await invokePromptTool(apiState, options, resolvedContext, {
510
+ command: 'prompt.update',
511
+ toolId: 'agentspace.prompt.update-prompt',
512
+ input,
513
+ successText: 'Prompt updated.',
514
+ });
515
+ }
516
+ catch (error) {
517
+ logError(error instanceof Error ? error.message : String(error));
518
+ process.exitCode = 1;
519
+ }
520
+ }
521
+ export async function runPromptDelete(options = {}) {
522
+ try {
523
+ ensureDestructiveWrite(options, 'This command deletes hosted prompts.');
524
+ const apiState = await requireApiState(options);
525
+ if (!apiState)
526
+ return;
527
+ const resolvedContext = await resolvePromptContext(options, apiState);
528
+ const id = ensurePromptId(options.id);
529
+ const input = { id };
530
+ await invokePromptTool(apiState, options, resolvedContext, {
531
+ command: 'prompt.delete',
532
+ toolId: 'agentspace.prompt.remove-prompt',
533
+ input,
534
+ successText: 'Prompt deleted.',
535
+ });
536
+ }
537
+ catch (error) {
538
+ logError(error instanceof Error ? error.message : String(error));
539
+ process.exitCode = 1;
540
+ }
541
+ }
542
+ async function loadPrompt(apiState, options, resolvedContext, id) {
543
+ const payload = await invokeHostedToolWithApiState(apiState, {
544
+ ...buildGatewayOptions(options, resolvedContext),
545
+ tenantId: options.tenantId,
546
+ locale: options.locale,
547
+ fallbackLocale: options.fallbackLocale,
548
+ timeoutMs: options.timeoutMs,
549
+ apiBaseUrl: options.apiBaseUrl,
550
+ accessToken: options.accessToken,
551
+ refreshToken: options.refreshToken,
552
+ toolId: 'agentspace.prompt.get-prompt',
553
+ input: { id },
554
+ });
555
+ const result = unwrapHostedToolResult(payload);
556
+ const prompt = unwrapResultData(result);
557
+ return isRecord(prompt) ? prompt : null;
558
+ }
559
+ async function loadPromptVersionById(apiState, options, resolvedContext, id) {
560
+ const payload = await invokeHostedToolWithApiState(apiState, {
561
+ ...buildGatewayOptions(options, resolvedContext),
562
+ tenantId: options.tenantId,
563
+ locale: options.locale,
564
+ fallbackLocale: options.fallbackLocale,
565
+ timeoutMs: options.timeoutMs,
566
+ apiBaseUrl: options.apiBaseUrl,
567
+ accessToken: options.accessToken,
568
+ refreshToken: options.refreshToken,
569
+ toolId: 'agentspace.prompt-version.get-prompt-version',
570
+ input: { id },
571
+ });
572
+ const result = unwrapHostedToolResult(payload);
573
+ const version = unwrapResultData(result);
574
+ return isRecord(version) ? version : null;
575
+ }
576
+ async function loadPromptVersions(apiState, options, resolvedContext, promptId, extraFilter = {}) {
577
+ const filter = compactPayload({
578
+ promptId,
579
+ projectId: normalizeNonEmpty(options.projectId) ?? normalizeNonEmpty(resolvedContext.projectId),
580
+ ...extraFilter,
581
+ });
582
+ const payload = await invokeHostedToolWithApiState(apiState, {
583
+ ...buildGatewayOptions(options, resolvedContext),
584
+ tenantId: options.tenantId,
585
+ locale: options.locale,
586
+ fallbackLocale: options.fallbackLocale,
587
+ timeoutMs: options.timeoutMs,
588
+ apiBaseUrl: options.apiBaseUrl,
589
+ accessToken: options.accessToken,
590
+ refreshToken: options.refreshToken,
591
+ toolId: 'agentspace.prompt-version.list-prompt-versions',
592
+ input: { filter },
593
+ });
594
+ return unwrapListItems(unwrapHostedToolResult(payload));
595
+ }
596
+ export async function runPromptInspect(options = {}) {
597
+ try {
598
+ const apiState = await requireApiState(options);
599
+ if (!apiState)
600
+ return;
601
+ const resolvedContext = await resolvePromptContext(options, apiState);
602
+ const id = ensurePromptId(options.id);
603
+ const prompt = await loadPrompt(apiState, options, resolvedContext, id);
604
+ if (!prompt)
605
+ throw new Error(`Prompt not found: ${id}`);
606
+ const versions = await loadPromptVersions(apiState, options, resolvedContext, id);
607
+ const currentVersionId = normalizeNonEmpty(prompt.currentVersionId);
608
+ const currentVersion = versions.find((entry) => normalizeNonEmpty(entry.id) === currentVersionId) ??
609
+ (currentVersionId ? await loadPromptVersionById(apiState, options, resolvedContext, currentVersionId) : null);
610
+ const result = compactPayload({
611
+ prompt,
612
+ versions,
613
+ currentVersion,
614
+ summary: compactPayload({
615
+ promptId: normalizeNonEmpty(prompt.id),
616
+ currentVersionId,
617
+ versionCount: versions.length,
618
+ }),
619
+ });
620
+ const outputResult = options.summary ? summarizePromptInspectResult(result) : result;
621
+ if (options.json) {
622
+ console.log(JSON.stringify(buildEnvelope({
623
+ command: 'prompt.inspect',
624
+ surface: 'prompt inspection pack',
625
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
626
+ input: { id },
627
+ result: outputResult,
628
+ }), null, 2));
629
+ return;
630
+ }
631
+ logSuccess('Prompt inspection pack ready.');
632
+ console.log(JSON.stringify(outputResult, null, 2));
633
+ }
634
+ catch (error) {
635
+ logError(error instanceof Error ? error.message : String(error));
636
+ process.exitCode = 1;
637
+ }
638
+ }
639
+ export async function runPromptCurrent(options = {}) {
640
+ try {
641
+ const apiState = await requireApiState(options);
642
+ if (!apiState)
643
+ return;
644
+ const resolvedContext = await resolvePromptContext(options, apiState);
645
+ const id = ensurePromptId(options.id);
646
+ const prompt = await loadPrompt(apiState, options, resolvedContext, id);
647
+ if (!prompt)
648
+ throw new Error(`Prompt not found: ${id}`);
649
+ const currentVersionId = normalizeNonEmpty(prompt.currentVersionId);
650
+ if (!currentVersionId) {
651
+ throw new Error(`Prompt ${id} does not have a currentVersionId. Publish or select a prompt version first.`);
652
+ }
653
+ const currentVersion = await loadPromptVersionById(apiState, options, resolvedContext, currentVersionId);
654
+ if (!currentVersion) {
655
+ throw new Error(`Current prompt version ${currentVersionId} could not be loaded.`);
656
+ }
657
+ const result = { prompt, currentVersion };
658
+ const outputResult = options.summary ? summarizePromptCurrentResult(result) : result;
659
+ if (options.json) {
660
+ console.log(JSON.stringify(buildEnvelope({
661
+ command: 'prompt.current',
662
+ surface: 'prompt current resolution',
663
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
664
+ input: { id },
665
+ artifacts: compactPayload({ promptId: normalizeNonEmpty(prompt.id), promptVersionId: currentVersionId }),
666
+ result: outputResult,
667
+ }), null, 2));
668
+ return;
669
+ }
670
+ logSuccess('Current prompt version loaded.');
671
+ console.log(JSON.stringify(outputResult, null, 2));
672
+ }
673
+ catch (error) {
674
+ logError(error instanceof Error ? error.message : String(error));
675
+ process.exitCode = 1;
676
+ }
677
+ }
678
+ export async function runPromptVersionList(options = {}) {
679
+ try {
680
+ const apiState = await requireApiState(options);
681
+ if (!apiState)
682
+ return;
683
+ const resolvedContext = await resolvePromptContext(options, apiState);
684
+ const input = {
685
+ filter: compactPayload({
686
+ promptId: normalizeNonEmpty(options.promptId),
687
+ projectId: normalizeNonEmpty(options.projectId) ?? normalizeNonEmpty(resolvedContext.projectId),
688
+ status: normalizeNonEmpty(options.status),
689
+ refType: normalizeNonEmpty(options.refType),
690
+ refId: normalizeNonEmpty(options.refId),
691
+ limit: options.limit !== undefined ? toInteger(options.limit, '--limit') : undefined,
692
+ }),
693
+ };
694
+ const payload = await invokeHostedToolWithApiState(apiState, {
695
+ ...buildGatewayOptions(options, resolvedContext),
696
+ tenantId: options.tenantId,
697
+ locale: options.locale,
698
+ fallbackLocale: options.fallbackLocale,
699
+ timeoutMs: options.timeoutMs,
700
+ apiBaseUrl: options.apiBaseUrl,
701
+ accessToken: options.accessToken,
702
+ refreshToken: options.refreshToken,
703
+ toolId: 'agentspace.prompt-version.list-prompt-versions',
704
+ input,
705
+ });
706
+ const result = unwrapHostedToolResult(payload);
707
+ const outputResult = options.summary ? summarizePromptVersionListResult(result) : result;
708
+ if (options.json) {
709
+ console.log(JSON.stringify(buildEnvelope({
710
+ command: 'prompt.version.list',
711
+ toolId: 'agentspace.prompt-version.list-prompt-versions',
712
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
713
+ input,
714
+ result: outputResult,
715
+ }), null, 2));
716
+ return;
717
+ }
718
+ logSuccess('Prompt version list loaded.');
719
+ console.log(JSON.stringify(outputResult, null, 2));
720
+ }
721
+ catch (error) {
722
+ logError(error instanceof Error ? error.message : String(error));
723
+ process.exitCode = 1;
724
+ }
725
+ }
726
+ export async function runPromptVersionGet(options = {}) {
727
+ try {
728
+ const apiState = await requireApiState(options);
729
+ if (!apiState)
730
+ return;
731
+ const resolvedContext = await resolvePromptContext(options, apiState);
732
+ const id = ensurePromptId(options.id);
733
+ const input = { id };
734
+ const payload = await invokeHostedToolWithApiState(apiState, {
735
+ ...buildGatewayOptions(options, resolvedContext),
736
+ tenantId: options.tenantId,
737
+ locale: options.locale,
738
+ fallbackLocale: options.fallbackLocale,
739
+ timeoutMs: options.timeoutMs,
740
+ apiBaseUrl: options.apiBaseUrl,
741
+ accessToken: options.accessToken,
742
+ refreshToken: options.refreshToken,
743
+ toolId: 'agentspace.prompt-version.get-prompt-version',
744
+ input,
745
+ });
746
+ const result = unwrapHostedToolResult(payload);
747
+ if (options.json) {
748
+ console.log(JSON.stringify(buildEnvelope({
749
+ command: 'prompt.version.get',
750
+ toolId: 'agentspace.prompt-version.get-prompt-version',
751
+ resolvedContext: buildResolvedContextRecord(resolvedContext),
752
+ input,
753
+ artifacts: collectPromptArtifacts(result),
754
+ result,
755
+ }), null, 2));
756
+ return;
757
+ }
758
+ logSuccess('Prompt version loaded.');
759
+ console.log(JSON.stringify(result, null, 2));
760
+ }
761
+ catch (error) {
762
+ logError(error instanceof Error ? error.message : String(error));
763
+ process.exitCode = 1;
764
+ }
765
+ }
766
+ export async function runPromptVersionCreate(options = {}) {
767
+ try {
768
+ const apiState = await requireApiState(options);
769
+ if (!apiState)
770
+ return;
771
+ const resolvedContext = await resolvePromptContext(options, apiState);
772
+ const seed = parseJsonSeed(options.input);
773
+ const promptId = resolveStringField(options.promptId, seed, 'promptId');
774
+ if (!promptId)
775
+ throw new Error('Prompt version create requires --prompt-id or input.promptId.');
776
+ const content = resolveTextField(options.content, seed, 'content');
777
+ if (!content)
778
+ throw new Error('Prompt version create requires --content or input.content.');
779
+ const projectId = requireProjectId(options, resolvedContext, seed);
780
+ const version = resolveIntegerField(options.version, seed, 'version', '--version') ??
781
+ resolveNextVersionNumber(await loadPromptVersions(apiState, { ...options, projectId }, { ...resolvedContext, projectId: normalizeNonEmpty(resolvedContext.projectId) ?? projectId }, promptId));
782
+ const input = {
783
+ data: compactPayload({
784
+ projectId,
785
+ promptId,
786
+ version,
787
+ status: resolveStringField(options.status, seed, 'status') ?? 'draft',
788
+ content,
789
+ variables: resolveUnknownField(options.variables, seed, 'variables', '--variables'),
790
+ meta: resolveUnknownField(options.meta, seed, 'meta', '--meta'),
791
+ refType: resolveStringField(options.refType, seed, 'refType'),
792
+ refId: resolveStringField(options.refId, seed, 'refId'),
793
+ }),
794
+ };
795
+ await invokePromptTool(apiState, options, resolvedContext, {
796
+ command: 'prompt.version.create',
797
+ toolId: 'agentspace.prompt-version.create',
798
+ input,
799
+ successText: 'Prompt version created.',
800
+ });
801
+ }
802
+ catch (error) {
803
+ logError(error instanceof Error ? error.message : String(error));
804
+ process.exitCode = 1;
805
+ }
806
+ }
807
+ export async function runPromptVersionUpdate(options = {}) {
808
+ try {
809
+ const apiState = await requireApiState(options);
810
+ if (!apiState)
811
+ return;
812
+ const resolvedContext = await resolvePromptContext(options, apiState);
813
+ const seed = parseJsonSeed(options.input);
814
+ const id = ensurePromptId(resolveStringField(options.id, seed, 'id'));
815
+ const patch = compactPayload({
816
+ projectId: normalizeNonEmpty(options.projectId) ??
817
+ normalizeNonEmpty(seed.projectId),
818
+ version: resolveIntegerField(options.version, seed, 'version', '--version'),
819
+ status: resolveStringField(options.status, seed, 'status'),
820
+ content: resolveTextField(options.content, seed, 'content'),
821
+ variables: resolveUnknownField(options.variables, seed, 'variables', '--variables'),
822
+ meta: resolveUnknownField(options.meta, seed, 'meta', '--meta'),
823
+ refType: resolveStringField(options.refType, seed, 'refType'),
824
+ refId: resolveStringField(options.refId, seed, 'refId'),
825
+ });
826
+ if (Object.keys(patch).length === 0) {
827
+ throw new Error('Provide at least one prompt version field to update.');
828
+ }
829
+ const input = { id, patch };
830
+ await invokePromptTool(apiState, options, resolvedContext, {
831
+ command: 'prompt.version.update',
832
+ toolId: 'agentspace.prompt-version.update-prompt-version',
833
+ input,
834
+ successText: 'Prompt version updated.',
835
+ });
836
+ }
837
+ catch (error) {
838
+ logError(error instanceof Error ? error.message : String(error));
839
+ process.exitCode = 1;
840
+ }
841
+ }
842
+ export async function runPromptVersionPublish(options = {}) {
843
+ try {
844
+ const apiState = await requireApiState(options);
845
+ if (!apiState)
846
+ return;
847
+ const resolvedContext = await resolvePromptContext(options, apiState);
848
+ const id = ensurePromptId(options.id);
849
+ const input = { id };
850
+ await invokePromptTool(apiState, options, resolvedContext, {
851
+ command: 'prompt.version.publish',
852
+ toolId: 'agentspace.prompt-version.publish-prompt-version',
853
+ input,
854
+ successText: 'Prompt version published.',
855
+ });
856
+ }
857
+ catch (error) {
858
+ logError(error instanceof Error ? error.message : String(error));
859
+ process.exitCode = 1;
860
+ }
861
+ }
862
+ export async function runPromptVersionDelete(options = {}) {
863
+ try {
864
+ ensureDestructiveWrite(options, 'This command deletes hosted prompt versions.');
865
+ const apiState = await requireApiState(options);
866
+ if (!apiState)
867
+ return;
868
+ const resolvedContext = await resolvePromptContext(options, apiState);
869
+ const id = ensurePromptId(options.id);
870
+ const input = { id };
871
+ await invokePromptTool(apiState, options, resolvedContext, {
872
+ command: 'prompt.version.delete',
873
+ toolId: 'agentspace.prompt-version.remove-prompt-version',
874
+ input,
875
+ successText: 'Prompt version deleted.',
876
+ });
877
+ }
878
+ catch (error) {
879
+ logError(error instanceof Error ? error.message : String(error));
880
+ process.exitCode = 1;
881
+ }
882
+ }
883
+ function applyPromptContextOptions(cmd, params = {}) {
884
+ applyCommonOptions(cmd);
885
+ cmd.option('--project-id <id>', 'Project id used to resolve repo-bound prompt ownership');
886
+ cmd.option('--project-name <name>', 'Project name used to resolve repo-bound prompt ownership');
887
+ cmd.option('--scope-id <id>', 'Explicit scope id override for prompt shell ownership');
888
+ if (params.withScopeResolution) {
889
+ cmd.option('--scope-resolution <mode>', 'Scope resolution policy: explicit or cascade');
890
+ }
891
+ return cmd;
892
+ }
893
+ function applyWriteGuards(cmd, params = {}) {
894
+ cmd.option('--preview', 'Return a validated preflight summary without executing the tool');
895
+ cmd.option('--apply', 'Execute the hosted write operation');
896
+ if (params.destructive) {
897
+ cmd.option('--confirm', 'Required with --apply for destructive deletes');
898
+ }
899
+ cmd.option('--idempotency-key <key>', 'Optional idempotency key for hosted writes');
900
+ return cmd;
901
+ }
902
+ function applyJsonSeedOption(cmd) {
903
+ cmd.option('--input <jsonOrFile>', 'Optional JSON object seed or @file.json');
904
+ return cmd;
905
+ }
906
+ export function makePromptCommand() {
907
+ const cmd = new Command('prompt').description('Agentspace prompt and prompt-version sugar commands over the hosted AOPS gateway');
908
+ applyPromptContextOptions(cmd.command('list')
909
+ .description('List reusable prompt shells')
910
+ .option('--name <text>', 'Prompt name filter')
911
+ .option('--status <status>', 'Prompt status filter')
912
+ .option('--tag <tag>', 'Prompt tag filter', collectRepeatedOption, [])
913
+ .option('--limit <n>', 'Optional item limit'), { withScopeResolution: true }).action(async (options) => {
914
+ await runPromptList(options);
915
+ });
916
+ applyPromptContextOptions(cmd.command('get')
917
+ .description('Get a prompt shell by id')
918
+ .requiredOption('--id <id>', 'Prompt id')).action(async (options) => {
919
+ await runPromptGet(options);
920
+ });
921
+ applyWriteGuards(applyJsonSeedOption(applyPromptContextOptions(cmd.command('create')
922
+ .description('Create a scope-owned prompt shell')
923
+ .requiredOption('--name <text>', 'Prompt name')
924
+ .option('--description <text>', 'Prompt description')
925
+ .option('--status <status>', 'Prompt status')
926
+ .option('--tag <tag>', 'Prompt tag', collectRepeatedOption, [])))).action(async (options) => {
927
+ await runPromptCreate(options);
928
+ });
929
+ applyWriteGuards(applyJsonSeedOption(applyPromptContextOptions(cmd.command('update')
930
+ .description('Update a prompt shell')
931
+ .requiredOption('--id <id>', 'Prompt id')
932
+ .option('--name <text>', 'Prompt name')
933
+ .option('--description <text>', 'Prompt description')
934
+ .option('--status <status>', 'Prompt status')
935
+ .option('--tag <tag>', 'Prompt tag', collectRepeatedOption, [])
936
+ .option('--current-version-id <id>', 'Explicitly set currentVersionId on the prompt shell')))).action(async (options) => {
937
+ await runPromptUpdate(options);
938
+ });
939
+ applyWriteGuards(applyPromptContextOptions(cmd.command('delete')
940
+ .description('Delete a prompt shell')
941
+ .requiredOption('--id <id>', 'Prompt id')), { destructive: true }).action(async (options) => {
942
+ await runPromptDelete(options);
943
+ });
944
+ applyPromptContextOptions(cmd.command('inspect')
945
+ .description('Load the prompt shell, versions, and current version together')
946
+ .requiredOption('--id <id>', 'Prompt id')
947
+ .option('--summary', 'Omit prompt-version content and print content size summaries')).action(async (options) => {
948
+ await runPromptInspect(options);
949
+ });
950
+ applyPromptContextOptions(cmd.command('current')
951
+ .description('Resolve the current prompt version for a prompt shell')
952
+ .requiredOption('--id <id>', 'Prompt id')
953
+ .option('--summary', 'Omit current version content and print content size summary')).action(async (options) => {
954
+ await runPromptCurrent(options);
955
+ });
956
+ const version = cmd.command('version').description('Prompt-version authoring and lifecycle commands');
957
+ applyPromptContextOptions(version.command('list')
958
+ .description('List prompt versions')
959
+ .option('--prompt-id <id>', 'Prompt id filter')
960
+ .option('--status <status>', 'Prompt version status filter')
961
+ .option('--ref-type <type>', 'Prompt version refType filter')
962
+ .option('--ref-id <id>', 'Prompt version refId filter')
963
+ .option('--limit <n>', 'Optional item limit')
964
+ .option('--summary', 'Omit prompt-version content and print content size summaries')).action(async (options) => {
965
+ await runPromptVersionList(options);
966
+ });
967
+ applyPromptContextOptions(version.command('get')
968
+ .description('Get a prompt version by id')
969
+ .requiredOption('--id <id>', 'Prompt version id')).action(async (options) => {
970
+ await runPromptVersionGet(options);
971
+ });
972
+ applyWriteGuards(applyJsonSeedOption(applyPromptContextOptions(version.command('create')
973
+ .description('Create a new prompt version')
974
+ .requiredOption('--prompt-id <id>', 'Prompt id')
975
+ .option('--version <n>', 'Optional explicit version number')
976
+ .option('--status <status>', 'Prompt version status')
977
+ .option('--content <textOrFile>', 'Prompt content or @file.md')
978
+ .option('--variables <jsonOrFile>', 'JSON variables object/array/value or @file.json')
979
+ .option('--meta <jsonOrFile>', 'JSON meta object/array/value or @file.json')
980
+ .option('--ref-type <type>', 'Optional refType linkage')
981
+ .option('--ref-id <id>', 'Optional refId linkage')))).action(async (options) => {
982
+ await runPromptVersionCreate(options);
983
+ });
984
+ applyWriteGuards(applyJsonSeedOption(applyPromptContextOptions(version.command('update')
985
+ .description('Update an existing prompt version')
986
+ .requiredOption('--id <id>', 'Prompt version id')
987
+ .option('--version <n>', 'Optional explicit version number')
988
+ .option('--status <status>', 'Prompt version status')
989
+ .option('--content <textOrFile>', 'Prompt content or @file.md')
990
+ .option('--variables <jsonOrFile>', 'JSON variables object/array/value or @file.json')
991
+ .option('--meta <jsonOrFile>', 'JSON meta object/array/value or @file.json')
992
+ .option('--ref-type <type>', 'Optional refType linkage')
993
+ .option('--ref-id <id>', 'Optional refId linkage')))).action(async (options) => {
994
+ await runPromptVersionUpdate(options);
995
+ });
996
+ applyWriteGuards(applyPromptContextOptions(version.command('publish')
997
+ .description('Publish a prompt version and sync the prompt current version')
998
+ .requiredOption('--id <id>', 'Prompt version id'))).action(async (options) => {
999
+ await runPromptVersionPublish(options);
1000
+ });
1001
+ applyWriteGuards(applyPromptContextOptions(version.command('delete')
1002
+ .description('Delete a prompt version')
1003
+ .requiredOption('--id <id>', 'Prompt version id')), { destructive: true }).action(async (options) => {
1004
+ await runPromptVersionDelete(options);
1005
+ });
1006
+ cmd.addHelpText('after', buildOperatorCookbook({
1007
+ examples: [
1008
+ 'aops-cli prompt create --name "Kickoff Template" --apply --json',
1009
+ 'aops-cli prompt version list --prompt-id <prompt-id> --summary --json',
1010
+ 'aops-cli prompt version create --prompt-id <prompt-id> --content @./template.md --apply --json',
1011
+ 'aops-cli prompt version publish --id <prompt-version-id> --apply --json',
1012
+ 'aops-cli prompt inspect --id <prompt-id> --summary --json',
1013
+ 'aops-cli prompt current --id <prompt-id> --summary --json',
1014
+ ],
1015
+ guide: GUIDE_PATHS.agentspace,
1016
+ notes: [
1017
+ 'Canonical reusable prompt truth lives in aops-server/DB; create/update/publish through these prompt commands.',
1018
+ '.aops/hosted/prompts/** is a read-only repo mirror refreshed by sync pull/bootstrap, not an authoring source.',
1019
+ 'Prompt version list/inspect/current are curated read surfaces and do not require --apply; use --summary unless you need full prompt-version content.',
1020
+ 'When --version is omitted, the CLI resolves the next version number from existing prompt versions.',
1021
+ ],
1022
+ }));
1023
+ return cmd;
1024
+ }