@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.
- package/LICENSE +19 -0
- package/NOTICE +7 -0
- package/README.md +203 -0
- package/assets/agent-assets/core/SKILL.md +49 -0
- package/assets/agent-assets/core/references/agentspace/SKILL.md +78 -0
- package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +108 -0
- package/assets/agent-assets/core/references/chatv3/SKILL.md +48 -0
- package/assets/agent-assets/core/references/collaborative-work/SKILL.md +85 -0
- package/assets/agent-assets/core/references/discuss/SKILL.md +66 -0
- package/assets/agent-assets/core/references/docman/SKILL.md +69 -0
- package/assets/agent-assets/core/references/hosted-chat/SKILL.md +64 -0
- package/assets/agent-assets/core/references/mission/SKILL.md +54 -0
- package/assets/agent-assets/core/references/projectman/SKILL.md +86 -0
- package/assets/agent-assets/core/references/sys/SKILL.md +36 -0
- package/assets/agent-assets/core/references/view/SKILL.md +58 -0
- package/assets/agent-assets/core/references/working-disciplines/SKILL.md +69 -0
- package/assets/agent-assets/core/user-guides/agent-assets.md +81 -0
- package/assets/agent-assets/core/user-guides/agentspace.md +1098 -0
- package/assets/agent-assets/core/user-guides/aops-cli.md +1107 -0
- package/assets/agent-assets/core/user-guides/aops-system.md +63 -0
- package/assets/agent-assets/core/user-guides/chatv3.md +113 -0
- package/assets/agent-assets/core/user-guides/docman.md +162 -0
- package/assets/agent-assets/core/user-guides/projectman.md +212 -0
- package/assets/agent-assets/core/user-guides/sys.md +94 -0
- package/assets/agent-assets/core/user-guides/working-disciplines.md +588 -0
- package/assets/agent-assets/gateway/aops/SKILL.md +14 -0
- package/assets/r6-remote-session-baseline.json +19 -0
- package/assets/skills/aops-install/SKILL.md +231 -0
- package/assets/skills/aops-install/agents/openai.yaml +4 -0
- package/dist/commands/activity.js +352 -0
- package/dist/commands/agent-profile.js +653 -0
- package/dist/commands/agent.js +710 -0
- package/dist/commands/agents-md.js +125 -0
- package/dist/commands/api.js +84 -0
- package/dist/commands/archive.js +873 -0
- package/dist/commands/artifact.js +535 -0
- package/dist/commands/assets.js +1414 -0
- package/dist/commands/auth/device-login.js +1 -0
- package/dist/commands/auth/legacy-export.js +177 -0
- package/dist/commands/auth/login.js +426 -0
- package/dist/commands/chat.js +1363 -0
- package/dist/commands/chatv3.js +1684 -0
- package/dist/commands/checkpoint.js +549 -0
- package/dist/commands/commercial-artifact.js +475 -0
- package/dist/commands/commercial-license.js +594 -0
- package/dist/commands/community-auth.js +62 -0
- package/dist/commands/community-cockpit.js +185 -0
- package/dist/commands/community-console.js +109 -0
- package/dist/commands/community-doctor.js +335 -0
- package/dist/commands/community-server.js +2062 -0
- package/dist/commands/community-setup.js +284 -0
- package/dist/commands/discuss.js +1448 -0
- package/dist/commands/doc.js +5219 -0
- package/dist/commands/experience.js +922 -0
- package/dist/commands/host.js +1127 -0
- package/dist/commands/init.js +118 -0
- package/dist/commands/memory.js +3129 -0
- package/dist/commands/mission.js +562 -0
- package/dist/commands/official-catalog.js +134 -0
- package/dist/commands/plan.js +84 -0
- package/dist/commands/playbook.js +415 -0
- package/dist/commands/pm/context.js +6 -0
- package/dist/commands/pm/index.js +701 -0
- package/dist/commands/pm/projectman.js +6266 -0
- package/dist/commands/project.js +1080 -0
- package/dist/commands/prompt.js +1024 -0
- package/dist/commands/repo-sync.js +1907 -0
- package/dist/commands/resource.js +527 -0
- package/dist/commands/skill.js +1211 -0
- package/dist/commands/start-disciplines.js +510 -0
- package/dist/commands/start.js +1343 -0
- package/dist/commands/target.js +309 -0
- package/dist/commands/version.js +42 -0
- package/dist/commands/view.js +1852 -0
- package/dist/launchers/cockpit.js +28 -0
- package/dist/launchers/options.js +74 -0
- package/dist/launchers/server.js +41 -0
- package/dist/lib/agent-assets/envelope.js +83 -0
- package/dist/lib/agent-assets/gateway.js +15 -0
- package/dist/lib/agent-assets/guards.js +23 -0
- package/dist/lib/agent-assets/hosted-discovery.js +148 -0
- package/dist/lib/agent-assets/hosted-package-input.js +154 -0
- package/dist/lib/agent-assets/legacy-pointer-migration.js +677 -0
- package/dist/lib/agent-assets/native-fs.js +589 -0
- package/dist/lib/agent-assets/package-manifest.js +324 -0
- package/dist/lib/agent-assets/portable-path.js +67 -0
- package/dist/lib/agent-assets/release-input.js +177 -0
- package/dist/lib/agent-assets/roots.js +45 -0
- package/dist/lib/agent-assets/runtime-binding-reader.js +545 -0
- package/dist/lib/agent-assets/runtime-targets.js +50 -0
- package/dist/lib/agent-assets/store-reader.js +1212 -0
- package/dist/lib/agent-assets/store-types.js +1 -0
- package/dist/lib/agent-assets/store-writer.js +1484 -0
- package/dist/lib/agent-assets/types.js +1 -0
- package/dist/lib/agent-assets/unicode-case-folding-v15-1.generated.js +1548 -0
- package/dist/lib/commercial-final-readiness.js +504 -0
- package/dist/lib/commercial-lifecycle-smoke-isolation.js +236 -0
- package/dist/lib/commercial-managed-postgres-docker-adapter.js +274 -0
- package/dist/lib/commercial-setup-readiness-adapter.js +179 -0
- package/dist/lib/community-client-contract.js +164 -0
- package/dist/lib/community-cockpit-lifecycle.js +601 -0
- package/dist/lib/community-command-abort.js +59 -0
- package/dist/lib/community-diagnostic.js +237 -0
- package/dist/lib/community-docker-adapter.js +498 -0
- package/dist/lib/community-home.js +31 -0
- package/dist/lib/community-instance-contract.js +148 -0
- package/dist/lib/community-instance-layout.js +97 -0
- package/dist/lib/community-lifecycle.js +1631 -0
- package/dist/lib/community-migration-snapshot.js +770 -0
- package/dist/lib/community-native-application-recovery.js +425 -0
- package/dist/lib/community-native-child.js +240 -0
- package/dist/lib/community-native-database-recovery.js +456 -0
- package/dist/lib/community-native-lifecycle.js +2458 -0
- package/dist/lib/community-native-migration.js +339 -0
- package/dist/lib/community-native-postgres.js +596 -0
- package/dist/lib/community-operation-journal.js +773 -0
- package/dist/lib/community-operation-lock.js +596 -0
- package/dist/lib/community-release-resolver.js +291 -0
- package/dist/lib/community-release-verifier.js +475 -0
- package/dist/lib/community-repo-discovery.js +252 -0
- package/dist/lib/community-setup-server-env.js +203 -0
- package/dist/lib/external-url.js +110 -0
- package/dist/lib/official-catalog-gateway.js +108 -0
- package/dist/lib/official-catalog.js +364 -0
- package/dist/lib/server-bootstrap.js +240 -0
- package/dist/lib/setup-agent-assets-bridge.js +176 -0
- package/dist/lib/setup-agent-assets-release.js +52 -0
- package/dist/lib/setup-external-postgres.js +108 -0
- package/dist/lib/setup-init-orchestrator.js +990 -0
- package/dist/lib/setup-install-guide.js +52 -0
- package/dist/lib/setup-installer-release.js +47 -0
- package/dist/lib/setup-local-postgres.js +329 -0
- package/dist/lib/setup-official-catalog-bridge.js +148 -0
- package/dist/lib/setup-readiness.js +888 -0
- package/dist/lib/tui-launcher.js +59 -0
- package/dist/main.js +150 -0
- package/dist/seeds/agents-md.js +54 -0
- package/dist/utils/agent-gateway.js +275 -0
- package/dist/utils/agents-md.js +281 -0
- package/dist/utils/api.js +255 -0
- package/dist/utils/chatv3-session-store.js +185 -0
- package/dist/utils/command.js +67 -0
- package/dist/utils/community-host-runtime.js +376 -0
- package/dist/utils/config.js +1015 -0
- package/dist/utils/discussion-workspace.js +552 -0
- package/dist/utils/experience-workspace.js +326 -0
- package/dist/utils/guide-paths.js +67 -0
- package/dist/utils/hosted-sugar.js +56 -0
- package/dist/utils/hosted-workspace.js +229 -0
- package/dist/utils/memory-workspace.js +537 -0
- package/dist/utils/operator-runtime.js +199 -0
- package/dist/utils/password-crypto.js +39 -0
- package/dist/utils/playbook-workspace.js +479 -0
- package/dist/utils/project-context.js +255 -0
- package/dist/utils/prompts.js +70 -0
- package/dist/utils/refresh-race.js +28 -0
- package/dist/utils/repo-config.js +109 -0
- package/dist/utils/repo-first-projectman.js +194 -0
- package/dist/utils/repo-first-storage.js +13 -0
- package/dist/utils/repo-first-view.js +305 -0
- package/dist/utils/session-guidance.js +278 -0
- package/dist/utils/session-state.js +137 -0
- package/dist/utils/table.js +39 -0
- package/dist/utils/transient-fs.js +49 -0
- package/dist/utils/workspace-root.js +1 -0
- package/launchers/aops-cockpit.ps1 +15 -0
- package/launchers/aops-cockpit.sh +16 -0
- package/launchers/aops-server.ps1 +15 -0
- package/launchers/aops-server.sh +16 -0
- package/native/tui/win32-x64/aops-tui.exe +0 -0
- package/package.json +81 -0
|
@@ -0,0 +1,535 @@
|
|
|
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, parseJsonInput, requireApiState, unwrapHostedToolResult, } from '../utils/agent-gateway.js';
|
|
5
|
+
import { resolveOwnerScopeIdFromBinding, resolveOwnerScopeIdFromProjectRecord, resolveProjectBindingContext, } from '../utils/project-context.js';
|
|
6
|
+
import { buildHostedSugarEnvelope, buildOperatorCookbook, ensureDestructiveWrite, ensureGuardedWrite, missingScopeIdMessage, } 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 parseJsonSeed(input, label = '--input') {
|
|
18
|
+
const normalized = normalizeNonEmpty(input);
|
|
19
|
+
if (!normalized)
|
|
20
|
+
return {};
|
|
21
|
+
const parsed = parseJsonInput(normalized, label);
|
|
22
|
+
if (!isRecord(parsed))
|
|
23
|
+
throw new Error(`${label} must be a JSON object or @file.json object.`);
|
|
24
|
+
return parsed;
|
|
25
|
+
}
|
|
26
|
+
function parseUnknownJsonInput(input, label) {
|
|
27
|
+
const normalized = normalizeNonEmpty(input);
|
|
28
|
+
if (!normalized)
|
|
29
|
+
return undefined;
|
|
30
|
+
return parseJsonInput(normalized, label);
|
|
31
|
+
}
|
|
32
|
+
function resolveStringField(explicit, seed, key) {
|
|
33
|
+
return normalizeNonEmpty(explicit) ?? normalizeNonEmpty(seed[key]);
|
|
34
|
+
}
|
|
35
|
+
function resolveUnknownField(explicit, seed, key, label) {
|
|
36
|
+
const explicitValue = parseUnknownJsonInput(explicit, label);
|
|
37
|
+
if (explicitValue !== undefined)
|
|
38
|
+
return explicitValue;
|
|
39
|
+
return seed[key];
|
|
40
|
+
}
|
|
41
|
+
function toInteger(value, label) {
|
|
42
|
+
if (typeof value === 'number' && Number.isInteger(value))
|
|
43
|
+
return value;
|
|
44
|
+
const normalized = normalizeNonEmpty(value);
|
|
45
|
+
if (!normalized)
|
|
46
|
+
throw new Error(`${label} must be an integer.`);
|
|
47
|
+
const parsed = Number.parseInt(normalized, 10);
|
|
48
|
+
if (!Number.isInteger(parsed))
|
|
49
|
+
throw new Error(`${label} must be an integer.`);
|
|
50
|
+
return parsed;
|
|
51
|
+
}
|
|
52
|
+
function resolveIntegerField(explicit, seed, key, label) {
|
|
53
|
+
if (explicit !== undefined && explicit !== null && explicit !== '')
|
|
54
|
+
return toInteger(explicit, label);
|
|
55
|
+
if (seed[key] !== undefined && seed[key] !== null && seed[key] !== '')
|
|
56
|
+
return toInteger(seed[key], label);
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
function extractId(value) {
|
|
60
|
+
return normalizeNonEmpty(value);
|
|
61
|
+
}
|
|
62
|
+
function collectArtifactArtifacts(result) {
|
|
63
|
+
const root = unwrapResultData(result) ?? (isRecord(result) ? result : {});
|
|
64
|
+
const artifacts = {};
|
|
65
|
+
const push = (key, value) => {
|
|
66
|
+
const normalized = extractId(value);
|
|
67
|
+
if (normalized)
|
|
68
|
+
artifacts[key] = normalized;
|
|
69
|
+
};
|
|
70
|
+
push('artifactId', root.artifactId);
|
|
71
|
+
if (!artifacts.artifactId)
|
|
72
|
+
push('artifactId', root.id);
|
|
73
|
+
push('artifactLinkId', root.artifactLinkId);
|
|
74
|
+
if (!artifacts.artifactLinkId && normalizeNonEmpty(root.artifactId))
|
|
75
|
+
push('artifactLinkId', root.id);
|
|
76
|
+
return Object.keys(artifacts).length > 0 ? artifacts : undefined;
|
|
77
|
+
}
|
|
78
|
+
function jsonByteLength(value) {
|
|
79
|
+
try {
|
|
80
|
+
return Buffer.byteLength(JSON.stringify(value), 'utf8');
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function summarizeText(value, maxLength = 180) {
|
|
87
|
+
const text = normalizeNonEmpty(value);
|
|
88
|
+
if (!text)
|
|
89
|
+
return undefined;
|
|
90
|
+
if (text.length <= maxLength)
|
|
91
|
+
return text;
|
|
92
|
+
return `${text.slice(0, maxLength - 3)}...`;
|
|
93
|
+
}
|
|
94
|
+
function summarizeMeta(value) {
|
|
95
|
+
if (value === undefined)
|
|
96
|
+
return undefined;
|
|
97
|
+
if (isRecord(value)) {
|
|
98
|
+
const keys = Object.keys(value).sort();
|
|
99
|
+
return compactPayload({
|
|
100
|
+
kind: 'object',
|
|
101
|
+
keyCount: keys.length,
|
|
102
|
+
keys,
|
|
103
|
+
bytes: jsonByteLength(value),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
return compactPayload({
|
|
108
|
+
kind: 'array',
|
|
109
|
+
length: value.length,
|
|
110
|
+
bytes: jsonByteLength(value),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return compactPayload({
|
|
114
|
+
kind: value === null ? 'null' : typeof value,
|
|
115
|
+
bytes: jsonByteLength(value),
|
|
116
|
+
preview: summarizeText(value, 80),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function summarizeArtifactRecord(value) {
|
|
120
|
+
if (!isRecord(value))
|
|
121
|
+
return value;
|
|
122
|
+
return compactPayload({
|
|
123
|
+
id: normalizeNonEmpty(value.id),
|
|
124
|
+
scopeId: normalizeNonEmpty(value.scopeId),
|
|
125
|
+
artifactType: normalizeNonEmpty(value.artifactType),
|
|
126
|
+
label: summarizeText(value.label),
|
|
127
|
+
storagePath: normalizeNonEmpty(value.storagePath),
|
|
128
|
+
mimeType: normalizeNonEmpty(value.mimeType),
|
|
129
|
+
sizeBytes: typeof value.sizeBytes === 'number' ? value.sizeBytes : undefined,
|
|
130
|
+
hash: normalizeNonEmpty(value.hash),
|
|
131
|
+
metaSummary: summarizeMeta(value.meta),
|
|
132
|
+
createdAt: normalizeNonEmpty(value.createdAt),
|
|
133
|
+
updatedAt: normalizeNonEmpty(value.updatedAt),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function summarizeArtifactGetResult(result) {
|
|
137
|
+
if (isRecord(result) && Object.prototype.hasOwnProperty.call(result, 'data')) {
|
|
138
|
+
return {
|
|
139
|
+
...result,
|
|
140
|
+
data: summarizeArtifactRecord(result.data),
|
|
141
|
+
summary: {
|
|
142
|
+
...(isRecord(result.summary) ? result.summary : {}),
|
|
143
|
+
mode: 'artifact-get-summary',
|
|
144
|
+
omitted: ['meta'],
|
|
145
|
+
fullRecordHint: 'Use `aops-cli artifact get --id <artifact-id> --json` without --summary for full metadata.',
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return summarizeArtifactRecord(result);
|
|
150
|
+
}
|
|
151
|
+
function summarizeArtifactRefListResult(result) {
|
|
152
|
+
if (Array.isArray(result))
|
|
153
|
+
return result.map(summarizeArtifactRecord);
|
|
154
|
+
if (isRecord(result) && Array.isArray(result.data)) {
|
|
155
|
+
const data = result.data.map(summarizeArtifactRecord);
|
|
156
|
+
return {
|
|
157
|
+
...result,
|
|
158
|
+
data,
|
|
159
|
+
summary: {
|
|
160
|
+
...(isRecord(result.summary) ? result.summary : {}),
|
|
161
|
+
mode: 'artifact-ref-list-summary',
|
|
162
|
+
count: data.length,
|
|
163
|
+
omitted: ['meta'],
|
|
164
|
+
fullRecordHint: 'Use `aops-cli artifact get --id <artifact-id> --json` for full metadata.',
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return summarizeArtifactGetResult(result);
|
|
169
|
+
}
|
|
170
|
+
function buildGatewayOptions(options, resolvedContext) {
|
|
171
|
+
return {
|
|
172
|
+
...options,
|
|
173
|
+
projectId: normalizeNonEmpty(options.projectId) ?? normalizeNonEmpty(resolvedContext.projectId),
|
|
174
|
+
projectName: normalizeNonEmpty(options.projectName) ?? normalizeNonEmpty(resolvedContext.projectName),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
async function hydrateProjectContext(apiState, options, resolvedContext) {
|
|
178
|
+
const projectId = normalizeNonEmpty(resolvedContext.projectId);
|
|
179
|
+
if (!projectId)
|
|
180
|
+
return resolvedContext;
|
|
181
|
+
if (normalizeNonEmpty(resolvedContext.scopeId) === projectId && normalizeNonEmpty(resolvedContext.projectName)) {
|
|
182
|
+
return resolvedContext;
|
|
183
|
+
}
|
|
184
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
185
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
186
|
+
toolId: 'agentspace.project.get-by-id',
|
|
187
|
+
input: { id: projectId },
|
|
188
|
+
});
|
|
189
|
+
const result = unwrapHostedToolResult(payload);
|
|
190
|
+
const project = unwrapResultData(result);
|
|
191
|
+
if (!isRecord(project))
|
|
192
|
+
return resolvedContext;
|
|
193
|
+
const scopeId = resolveOwnerScopeIdFromProjectRecord(project, resolvedContext.scopeId);
|
|
194
|
+
const projectName = normalizeNonEmpty(project.name) ?? resolvedContext.projectName;
|
|
195
|
+
return {
|
|
196
|
+
...resolvedContext,
|
|
197
|
+
scopeId,
|
|
198
|
+
projectName,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function resolveArtifactContext(options, apiState) {
|
|
202
|
+
const resolved = await resolveProjectBindingContext(options, {
|
|
203
|
+
requireProject: false,
|
|
204
|
+
});
|
|
205
|
+
const scopeId = normalizeNonEmpty(options.scopeId) ?? resolveOwnerScopeIdFromBinding(resolved);
|
|
206
|
+
return hydrateProjectContext(apiState, options, {
|
|
207
|
+
...resolved,
|
|
208
|
+
scopeId,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function buildResolvedContextRecord(context) {
|
|
212
|
+
return compactPayload({
|
|
213
|
+
repoRoot: context.repoRoot,
|
|
214
|
+
configPath: context.configPath,
|
|
215
|
+
configFound: context.configFound,
|
|
216
|
+
scopeId: context.scopeId,
|
|
217
|
+
projectId: context.projectId,
|
|
218
|
+
projectName: context.projectName,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
const buildEnvelope = buildHostedSugarEnvelope;
|
|
222
|
+
function ensureArtifactId(id, label = '--id') {
|
|
223
|
+
const resolved = normalizeNonEmpty(id);
|
|
224
|
+
if (!resolved)
|
|
225
|
+
throw new Error(`Provide ${label}.`);
|
|
226
|
+
return resolved;
|
|
227
|
+
}
|
|
228
|
+
function requireScopeId(context, seed) {
|
|
229
|
+
const scopeId = normalizeNonEmpty(context.scopeId) ?? normalizeNonEmpty(seed.scopeId);
|
|
230
|
+
if (!scopeId) {
|
|
231
|
+
throw new Error(missingScopeIdMessage('Artifact create'));
|
|
232
|
+
}
|
|
233
|
+
return scopeId;
|
|
234
|
+
}
|
|
235
|
+
function requireProjectId(context, seed) {
|
|
236
|
+
const projectId = normalizeNonEmpty(context.projectId) ??
|
|
237
|
+
normalizeNonEmpty(seed.projectId);
|
|
238
|
+
if (!projectId) {
|
|
239
|
+
throw new Error('Artifact link requires repo-bound project context or --project-id / input.projectId.');
|
|
240
|
+
}
|
|
241
|
+
return projectId;
|
|
242
|
+
}
|
|
243
|
+
async function invokeArtifactTool(apiState, options, resolvedContext, params) {
|
|
244
|
+
ensureGuardedWrite(options, 'This command mutates hosted artifact state.');
|
|
245
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
246
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
247
|
+
tenantId: options.tenantId,
|
|
248
|
+
locale: options.locale,
|
|
249
|
+
fallbackLocale: options.fallbackLocale,
|
|
250
|
+
timeoutMs: options.timeoutMs,
|
|
251
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
252
|
+
accessToken: options.accessToken,
|
|
253
|
+
refreshToken: options.refreshToken,
|
|
254
|
+
toolId: params.toolId,
|
|
255
|
+
input: params.input,
|
|
256
|
+
preview: options.preview,
|
|
257
|
+
apply: options.apply,
|
|
258
|
+
confirm: options.confirm,
|
|
259
|
+
idempotencyKey: options.idempotencyKey,
|
|
260
|
+
});
|
|
261
|
+
const result = unwrapHostedToolResult(payload);
|
|
262
|
+
if (options.json) {
|
|
263
|
+
console.log(JSON.stringify(buildEnvelope({
|
|
264
|
+
command: params.command,
|
|
265
|
+
toolId: params.toolId,
|
|
266
|
+
resolvedContext: buildResolvedContextRecord(resolvedContext),
|
|
267
|
+
input: params.input,
|
|
268
|
+
artifacts: collectArtifactArtifacts(result),
|
|
269
|
+
result,
|
|
270
|
+
}), null, 2));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
logSuccess(params.successText);
|
|
274
|
+
console.log(JSON.stringify(result, null, 2));
|
|
275
|
+
}
|
|
276
|
+
export async function runArtifactGet(options = {}) {
|
|
277
|
+
try {
|
|
278
|
+
const apiState = await requireApiState(options);
|
|
279
|
+
if (!apiState)
|
|
280
|
+
return;
|
|
281
|
+
const resolvedContext = await resolveArtifactContext(options, apiState);
|
|
282
|
+
const id = ensureArtifactId(options.id);
|
|
283
|
+
const input = { id };
|
|
284
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
285
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
286
|
+
tenantId: options.tenantId,
|
|
287
|
+
locale: options.locale,
|
|
288
|
+
fallbackLocale: options.fallbackLocale,
|
|
289
|
+
timeoutMs: options.timeoutMs,
|
|
290
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
291
|
+
accessToken: options.accessToken,
|
|
292
|
+
refreshToken: options.refreshToken,
|
|
293
|
+
toolId: 'agentspace.artifact.get-artifact',
|
|
294
|
+
input,
|
|
295
|
+
});
|
|
296
|
+
const result = unwrapHostedToolResult(payload);
|
|
297
|
+
const outputResult = options.summary ? summarizeArtifactGetResult(result) : result;
|
|
298
|
+
if (options.json) {
|
|
299
|
+
console.log(JSON.stringify(buildEnvelope({
|
|
300
|
+
command: 'artifact.get',
|
|
301
|
+
toolId: 'agentspace.artifact.get-artifact',
|
|
302
|
+
resolvedContext: buildResolvedContextRecord(resolvedContext),
|
|
303
|
+
input,
|
|
304
|
+
artifacts: collectArtifactArtifacts(result),
|
|
305
|
+
result: outputResult,
|
|
306
|
+
}), null, 2));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
logSuccess('Artifact loaded.');
|
|
310
|
+
console.log(JSON.stringify(outputResult, null, 2));
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
314
|
+
process.exitCode = 1;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
export async function runArtifactCreate(options = {}) {
|
|
318
|
+
try {
|
|
319
|
+
const apiState = await requireApiState(options);
|
|
320
|
+
if (!apiState)
|
|
321
|
+
return;
|
|
322
|
+
const resolvedContext = await resolveArtifactContext(options, apiState);
|
|
323
|
+
const seed = parseJsonSeed(options.input);
|
|
324
|
+
const artifactType = resolveStringField(options.artifactType, seed, 'artifactType');
|
|
325
|
+
const storagePath = resolveStringField(options.storagePath, seed, 'storagePath');
|
|
326
|
+
if (!artifactType)
|
|
327
|
+
throw new Error('Artifact create requires --artifact-type or input.artifactType.');
|
|
328
|
+
if (!storagePath)
|
|
329
|
+
throw new Error('Artifact create requires --storage-path or input.storagePath.');
|
|
330
|
+
const input = {
|
|
331
|
+
data: compactPayload({
|
|
332
|
+
scopeId: requireScopeId(resolvedContext, seed),
|
|
333
|
+
artifactType,
|
|
334
|
+
storagePath,
|
|
335
|
+
label: resolveStringField(options.label, seed, 'label'),
|
|
336
|
+
mimeType: resolveStringField(options.mimeType, seed, 'mimeType'),
|
|
337
|
+
sizeBytes: resolveIntegerField(options.sizeBytes, seed, 'sizeBytes', '--size-bytes'),
|
|
338
|
+
hash: resolveStringField(options.hash, seed, 'hash'),
|
|
339
|
+
meta: resolveUnknownField(options.meta, seed, 'meta', '--meta'),
|
|
340
|
+
}),
|
|
341
|
+
};
|
|
342
|
+
await invokeArtifactTool(apiState, options, resolvedContext, {
|
|
343
|
+
command: 'artifact.create',
|
|
344
|
+
toolId: 'agentspace.artifact.store-artifact',
|
|
345
|
+
input,
|
|
346
|
+
successText: 'Artifact created.',
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
351
|
+
process.exitCode = 1;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
export async function runArtifactDelete(options = {}) {
|
|
355
|
+
try {
|
|
356
|
+
ensureDestructiveWrite(options, 'This command deletes hosted artifacts.');
|
|
357
|
+
const apiState = await requireApiState(options);
|
|
358
|
+
if (!apiState)
|
|
359
|
+
return;
|
|
360
|
+
const resolvedContext = await resolveArtifactContext(options, apiState);
|
|
361
|
+
const id = ensureArtifactId(options.id);
|
|
362
|
+
const input = { id };
|
|
363
|
+
await invokeArtifactTool(apiState, options, resolvedContext, {
|
|
364
|
+
command: 'artifact.delete',
|
|
365
|
+
toolId: 'agentspace.artifact.remove-artifact',
|
|
366
|
+
input,
|
|
367
|
+
successText: 'Artifact deleted.',
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
372
|
+
process.exitCode = 1;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
export async function runArtifactLink(options = {}) {
|
|
376
|
+
try {
|
|
377
|
+
const apiState = await requireApiState(options);
|
|
378
|
+
if (!apiState)
|
|
379
|
+
return;
|
|
380
|
+
const resolvedContext = await resolveArtifactContext(options, apiState);
|
|
381
|
+
const seed = parseJsonSeed(options.input);
|
|
382
|
+
const artifactId = resolveStringField(options.artifactId, seed, 'artifactId');
|
|
383
|
+
const refType = resolveStringField(options.refType, seed, 'refType');
|
|
384
|
+
const refId = resolveStringField(options.refId, seed, 'refId');
|
|
385
|
+
if (!artifactId)
|
|
386
|
+
throw new Error('Artifact link requires --artifact-id or input.artifactId.');
|
|
387
|
+
if (!refType)
|
|
388
|
+
throw new Error('Artifact link requires --ref-type or input.refType.');
|
|
389
|
+
if (!refId)
|
|
390
|
+
throw new Error('Artifact link requires --ref-id or input.refId.');
|
|
391
|
+
const input = {
|
|
392
|
+
data: compactPayload({
|
|
393
|
+
projectId: requireProjectId({
|
|
394
|
+
...resolvedContext,
|
|
395
|
+
projectId: normalizeNonEmpty(options.projectId) ?? resolvedContext.projectId,
|
|
396
|
+
}, seed),
|
|
397
|
+
artifactId,
|
|
398
|
+
refType,
|
|
399
|
+
refId,
|
|
400
|
+
createdBy: resolveStringField(undefined, seed, 'createdBy'),
|
|
401
|
+
}),
|
|
402
|
+
};
|
|
403
|
+
await invokeArtifactTool(apiState, options, resolvedContext, {
|
|
404
|
+
command: 'artifact.link',
|
|
405
|
+
toolId: 'agentspace.artifact.link-artifact',
|
|
406
|
+
input,
|
|
407
|
+
successText: 'Artifact linked.',
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
412
|
+
process.exitCode = 1;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
export async function runArtifactRefList(options = {}) {
|
|
416
|
+
try {
|
|
417
|
+
const apiState = await requireApiState(options);
|
|
418
|
+
if (!apiState)
|
|
419
|
+
return;
|
|
420
|
+
const resolvedContext = await resolveArtifactContext(options, apiState);
|
|
421
|
+
const refType = ensureArtifactId(options.refType, '--ref-type');
|
|
422
|
+
const refId = ensureArtifactId(options.refId, '--ref-id');
|
|
423
|
+
const input = compactPayload({
|
|
424
|
+
refType,
|
|
425
|
+
refId,
|
|
426
|
+
scopeId: normalizeNonEmpty(options.scopeId) ?? normalizeNonEmpty(resolvedContext.scopeId),
|
|
427
|
+
scopeResolution: options.scopeResolution,
|
|
428
|
+
});
|
|
429
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
430
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
431
|
+
tenantId: options.tenantId,
|
|
432
|
+
locale: options.locale,
|
|
433
|
+
fallbackLocale: options.fallbackLocale,
|
|
434
|
+
timeoutMs: options.timeoutMs,
|
|
435
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
436
|
+
accessToken: options.accessToken,
|
|
437
|
+
refreshToken: options.refreshToken,
|
|
438
|
+
toolId: 'agentspace.artifact.list-artifacts-by-ref',
|
|
439
|
+
input,
|
|
440
|
+
});
|
|
441
|
+
const result = unwrapHostedToolResult(payload);
|
|
442
|
+
const outputResult = options.summary ? summarizeArtifactRefListResult(result) : result;
|
|
443
|
+
if (options.json) {
|
|
444
|
+
console.log(JSON.stringify(buildEnvelope({
|
|
445
|
+
command: 'artifact.ref.list',
|
|
446
|
+
toolId: 'agentspace.artifact.list-artifacts-by-ref',
|
|
447
|
+
resolvedContext: buildResolvedContextRecord(resolvedContext),
|
|
448
|
+
input,
|
|
449
|
+
result: outputResult,
|
|
450
|
+
}), null, 2));
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
logSuccess('Artifact ref list loaded.');
|
|
454
|
+
console.log(JSON.stringify(outputResult, null, 2));
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
458
|
+
process.exitCode = 1;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function applyArtifactContextOptions(cmd, params = {}) {
|
|
462
|
+
applyCommonOptions(cmd);
|
|
463
|
+
cmd.option('--project-id <id>', 'Project id used to resolve repo-bound artifact ownership or linking');
|
|
464
|
+
cmd.option('--project-name <name>', 'Project name used to resolve repo-bound artifact ownership');
|
|
465
|
+
cmd.option('--scope-id <id>', 'Explicit scope id override for artifact ownership');
|
|
466
|
+
if (params.withScopeResolution) {
|
|
467
|
+
cmd.option('--scope-resolution <mode>', 'Scope resolution policy: explicit or cascade');
|
|
468
|
+
}
|
|
469
|
+
return cmd;
|
|
470
|
+
}
|
|
471
|
+
function applyWriteGuards(cmd, params = {}) {
|
|
472
|
+
cmd.option('--preview', 'Return a validated preflight summary without executing the tool');
|
|
473
|
+
cmd.option('--apply', 'Execute the hosted write operation');
|
|
474
|
+
if (params.destructive) {
|
|
475
|
+
cmd.option('--confirm', 'Required with --apply for destructive deletes');
|
|
476
|
+
}
|
|
477
|
+
cmd.option('--idempotency-key <key>', 'Optional idempotency key for hosted writes');
|
|
478
|
+
return cmd;
|
|
479
|
+
}
|
|
480
|
+
function applyJsonSeedOption(cmd) {
|
|
481
|
+
cmd.option('--input <jsonOrFile>', 'Optional JSON object seed or @file.json');
|
|
482
|
+
return cmd;
|
|
483
|
+
}
|
|
484
|
+
export function makeArtifactCommand() {
|
|
485
|
+
const cmd = new Command('artifact').description('Agentspace artifact sugar commands over the hosted AOPS gateway');
|
|
486
|
+
applyArtifactContextOptions(cmd.command('get')
|
|
487
|
+
.description('Get an artifact by id')
|
|
488
|
+
.requiredOption('--id <id>', 'Artifact id')
|
|
489
|
+
.option('--summary', 'Omit raw artifact meta and print metadata size summary')).action(async (options) => {
|
|
490
|
+
await runArtifactGet(options);
|
|
491
|
+
});
|
|
492
|
+
applyWriteGuards(applyJsonSeedOption(applyArtifactContextOptions(cmd.command('create')
|
|
493
|
+
.description('Create a scope-owned artifact shell')
|
|
494
|
+
.requiredOption('--artifact-type <type>', 'Artifact type')
|
|
495
|
+
.requiredOption('--storage-path <path>', 'Artifact storage path')
|
|
496
|
+
.option('--label <text>', 'Artifact label')
|
|
497
|
+
.option('--mime-type <text>', 'Artifact mime type')
|
|
498
|
+
.option('--size-bytes <n>', 'Artifact byte size')
|
|
499
|
+
.option('--hash <text>', 'Artifact hash')
|
|
500
|
+
.option('--meta <jsonOrFile>', 'JSON meta object/array/value or @file.json')))).action(async (options) => {
|
|
501
|
+
await runArtifactCreate(options);
|
|
502
|
+
});
|
|
503
|
+
applyWriteGuards(applyJsonSeedOption(applyArtifactContextOptions(cmd.command('link')
|
|
504
|
+
.description('Link an artifact to a project-scoped ref')
|
|
505
|
+
.requiredOption('--artifact-id <id>', 'Artifact id')
|
|
506
|
+
.requiredOption('--ref-type <type>', 'Ref type')
|
|
507
|
+
.requiredOption('--ref-id <id>', 'Ref id')))).action(async (options) => {
|
|
508
|
+
await runArtifactLink(options);
|
|
509
|
+
});
|
|
510
|
+
const ref = cmd.command('ref').description('Artifact ref lookup commands');
|
|
511
|
+
applyArtifactContextOptions(ref.command('list')
|
|
512
|
+
.description('List artifacts linked to a ref')
|
|
513
|
+
.requiredOption('--ref-type <type>', 'Ref type')
|
|
514
|
+
.requiredOption('--ref-id <id>', 'Ref id')
|
|
515
|
+
.option('--summary', 'Print compact artifact records and omit raw meta payloads'), { withScopeResolution: true }).action(async (options) => {
|
|
516
|
+
await runArtifactRefList(options);
|
|
517
|
+
});
|
|
518
|
+
applyWriteGuards(applyArtifactContextOptions(cmd.command('delete')
|
|
519
|
+
.description('Delete an artifact')
|
|
520
|
+
.requiredOption('--id <id>', 'Artifact id')), { destructive: true }).action(async (options) => {
|
|
521
|
+
await runArtifactDelete(options);
|
|
522
|
+
});
|
|
523
|
+
cmd.addHelpText('after', buildOperatorCookbook({
|
|
524
|
+
examples: [
|
|
525
|
+
'aops-cli artifact create --artifact-type file --storage-path s3://bucket/report.json --apply --json',
|
|
526
|
+
'aops-cli artifact link --artifact-id <artifact-id> --ref-type resource --ref-id <resource-id> --apply --json',
|
|
527
|
+
'aops-cli artifact ref list --ref-type resource --ref-id <resource-id> --summary --json',
|
|
528
|
+
'aops-cli artifact get --id <artifact-id> --summary --json',
|
|
529
|
+
'aops-cli artifact delete --id <artifact-id> --apply --confirm --json',
|
|
530
|
+
],
|
|
531
|
+
guide: GUIDE_PATHS.agentspace,
|
|
532
|
+
notes: ['Artifact get/ref list are curated read surfaces and do not require --apply; use --summary unless you need full meta.'],
|
|
533
|
+
}));
|
|
534
|
+
return cmd;
|
|
535
|
+
}
|