@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,527 @@
|
|
|
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 { preferProjectNameBinding, 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 collectRepeatedOption(value, previous = []) {
|
|
18
|
+
const normalized = normalizeNonEmpty(value);
|
|
19
|
+
return normalized ? [...previous, normalized] : previous;
|
|
20
|
+
}
|
|
21
|
+
function toInteger(value, label) {
|
|
22
|
+
if (typeof value === 'number' && Number.isInteger(value))
|
|
23
|
+
return value;
|
|
24
|
+
const normalized = normalizeNonEmpty(value);
|
|
25
|
+
if (!normalized)
|
|
26
|
+
throw new Error(`${label} must be an integer.`);
|
|
27
|
+
const parsed = Number.parseInt(normalized, 10);
|
|
28
|
+
if (!Number.isInteger(parsed))
|
|
29
|
+
throw new Error(`${label} must be an integer.`);
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
function toStringArray(values) {
|
|
33
|
+
return Array.isArray(values)
|
|
34
|
+
? values.map((entry) => normalizeNonEmpty(entry)).filter((entry) => Boolean(entry))
|
|
35
|
+
: [];
|
|
36
|
+
}
|
|
37
|
+
function parseJsonSeed(input, label = '--input') {
|
|
38
|
+
const normalized = normalizeNonEmpty(input);
|
|
39
|
+
if (!normalized)
|
|
40
|
+
return {};
|
|
41
|
+
const parsed = parseJsonInput(normalized, label);
|
|
42
|
+
if (!isRecord(parsed))
|
|
43
|
+
throw new Error(`${label} must be a JSON object or @file.json object.`);
|
|
44
|
+
return parsed;
|
|
45
|
+
}
|
|
46
|
+
function parseUnknownJsonInput(input, label) {
|
|
47
|
+
const normalized = normalizeNonEmpty(input);
|
|
48
|
+
if (!normalized)
|
|
49
|
+
return undefined;
|
|
50
|
+
return parseJsonInput(normalized, label);
|
|
51
|
+
}
|
|
52
|
+
function resolveStringField(explicit, seed, key) {
|
|
53
|
+
return normalizeNonEmpty(explicit) ?? normalizeNonEmpty(seed[key]);
|
|
54
|
+
}
|
|
55
|
+
function resolveStringArrayField(explicit, seed, key) {
|
|
56
|
+
const explicitValues = toStringArray(explicit);
|
|
57
|
+
if (explicitValues.length > 0)
|
|
58
|
+
return explicitValues;
|
|
59
|
+
const seededValues = toStringArray(seed[key]);
|
|
60
|
+
return seededValues.length > 0 ? seededValues : undefined;
|
|
61
|
+
}
|
|
62
|
+
function resolveUnknownField(explicit, seed, key, label) {
|
|
63
|
+
const explicitValue = parseUnknownJsonInput(explicit, label);
|
|
64
|
+
if (explicitValue !== undefined)
|
|
65
|
+
return explicitValue;
|
|
66
|
+
return seed[key];
|
|
67
|
+
}
|
|
68
|
+
function extractId(value) {
|
|
69
|
+
return normalizeNonEmpty(value);
|
|
70
|
+
}
|
|
71
|
+
function collectResourceArtifacts(result) {
|
|
72
|
+
const root = unwrapResultData(result) ?? (isRecord(result) ? result : {});
|
|
73
|
+
const resourceId = extractId(root?.resourceId) ?? extractId(root?.id);
|
|
74
|
+
return resourceId ? { resourceId } : undefined;
|
|
75
|
+
}
|
|
76
|
+
function jsonByteLength(value) {
|
|
77
|
+
try {
|
|
78
|
+
return Buffer.byteLength(JSON.stringify(value), 'utf8');
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function summarizeText(value, maxLength = 180) {
|
|
85
|
+
const text = normalizeNonEmpty(value);
|
|
86
|
+
if (!text)
|
|
87
|
+
return undefined;
|
|
88
|
+
if (text.length <= maxLength)
|
|
89
|
+
return text;
|
|
90
|
+
return `${text.slice(0, maxLength - 3)}...`;
|
|
91
|
+
}
|
|
92
|
+
function summarizeMeta(value) {
|
|
93
|
+
if (value === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
if (isRecord(value)) {
|
|
96
|
+
const keys = Object.keys(value).sort();
|
|
97
|
+
return compactPayload({
|
|
98
|
+
kind: 'object',
|
|
99
|
+
keyCount: keys.length,
|
|
100
|
+
keys,
|
|
101
|
+
bytes: jsonByteLength(value),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (Array.isArray(value)) {
|
|
105
|
+
return compactPayload({
|
|
106
|
+
kind: 'array',
|
|
107
|
+
length: value.length,
|
|
108
|
+
bytes: jsonByteLength(value),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return compactPayload({
|
|
112
|
+
kind: value === null ? 'null' : typeof value,
|
|
113
|
+
bytes: jsonByteLength(value),
|
|
114
|
+
preview: summarizeText(value, 80),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function summarizeResourceRecord(value) {
|
|
118
|
+
if (!isRecord(value))
|
|
119
|
+
return value;
|
|
120
|
+
const description = normalizeNonEmpty(value.description);
|
|
121
|
+
const descriptionPreview = summarizeText(description);
|
|
122
|
+
return compactPayload({
|
|
123
|
+
id: normalizeNonEmpty(value.id),
|
|
124
|
+
scopeId: normalizeNonEmpty(value.scopeId),
|
|
125
|
+
projectId: normalizeNonEmpty(value.projectId),
|
|
126
|
+
name: normalizeNonEmpty(value.name),
|
|
127
|
+
resourceType: normalizeNonEmpty(value.resourceType),
|
|
128
|
+
uri: normalizeNonEmpty(value.uri),
|
|
129
|
+
url: normalizeNonEmpty(value.url),
|
|
130
|
+
refType: normalizeNonEmpty(value.refType),
|
|
131
|
+
refId: normalizeNonEmpty(value.refId),
|
|
132
|
+
tags: Array.isArray(value.tags) ? value.tags : undefined,
|
|
133
|
+
description: descriptionPreview,
|
|
134
|
+
descriptionBytes: description ? Buffer.byteLength(description, 'utf8') : undefined,
|
|
135
|
+
descriptionTruncated: description && descriptionPreview !== description ? true : undefined,
|
|
136
|
+
metaSummary: summarizeMeta(value.meta),
|
|
137
|
+
createdAt: normalizeNonEmpty(value.createdAt),
|
|
138
|
+
updatedAt: normalizeNonEmpty(value.updatedAt),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function summarizeResourceListResult(result) {
|
|
142
|
+
if (Array.isArray(result)) {
|
|
143
|
+
return result.map(summarizeResourceRecord);
|
|
144
|
+
}
|
|
145
|
+
if (isRecord(result) && Array.isArray(result.data)) {
|
|
146
|
+
const data = result.data.map(summarizeResourceRecord);
|
|
147
|
+
return {
|
|
148
|
+
...result,
|
|
149
|
+
data,
|
|
150
|
+
summary: {
|
|
151
|
+
mode: 'resource-list-summary',
|
|
152
|
+
count: data.length,
|
|
153
|
+
omitted: ['meta'],
|
|
154
|
+
fullRecordHint: 'Use `aops-cli resource get --id <resource-id> --json` for full metadata.',
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return summarizeResourceRecord(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
|
+
}
|
|
173
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
174
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
175
|
+
toolId: 'agentspace.project.get-by-id',
|
|
176
|
+
input: { id: projectId },
|
|
177
|
+
});
|
|
178
|
+
const result = unwrapHostedToolResult(payload);
|
|
179
|
+
const project = unwrapResultData(result);
|
|
180
|
+
if (!isRecord(project))
|
|
181
|
+
return resolvedContext;
|
|
182
|
+
const scopeId = resolveOwnerScopeIdFromProjectRecord(project, resolvedContext.scopeId);
|
|
183
|
+
const projectName = normalizeNonEmpty(project.name) ?? resolvedContext.projectName;
|
|
184
|
+
return {
|
|
185
|
+
...resolvedContext,
|
|
186
|
+
scopeId,
|
|
187
|
+
projectName,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
async function resolveResourceContext(options, apiState) {
|
|
191
|
+
const resolved = await resolveProjectBindingContext(options, {
|
|
192
|
+
requireProject: false,
|
|
193
|
+
});
|
|
194
|
+
const scopeId = normalizeNonEmpty(options.scopeId) ?? resolveOwnerScopeIdFromBinding(resolved);
|
|
195
|
+
return hydrateProjectContext(apiState, options, {
|
|
196
|
+
...resolved,
|
|
197
|
+
scopeId,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function buildResolvedContextRecord(context) {
|
|
201
|
+
return compactPayload({
|
|
202
|
+
repoRoot: context.repoRoot,
|
|
203
|
+
configPath: context.configPath,
|
|
204
|
+
configFound: context.configFound,
|
|
205
|
+
scopeId: context.scopeId,
|
|
206
|
+
projectId: context.projectId,
|
|
207
|
+
projectName: context.projectName,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
const buildEnvelope = buildHostedSugarEnvelope;
|
|
211
|
+
function ensureResourceId(id, label = '--id') {
|
|
212
|
+
const resolved = normalizeNonEmpty(id);
|
|
213
|
+
if (!resolved)
|
|
214
|
+
throw new Error(`Provide ${label}.`);
|
|
215
|
+
return resolved;
|
|
216
|
+
}
|
|
217
|
+
function requireScopeId(context, seed) {
|
|
218
|
+
const scopeId = normalizeNonEmpty(context.scopeId) ?? normalizeNonEmpty(seed.scopeId);
|
|
219
|
+
if (!scopeId) {
|
|
220
|
+
throw new Error(missingScopeIdMessage('Resource create'));
|
|
221
|
+
}
|
|
222
|
+
return scopeId;
|
|
223
|
+
}
|
|
224
|
+
async function invokeResourceTool(apiState, options, resolvedContext, params) {
|
|
225
|
+
ensureGuardedWrite(options, 'This command mutates hosted resource state.');
|
|
226
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
227
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
228
|
+
tenantId: options.tenantId,
|
|
229
|
+
locale: options.locale,
|
|
230
|
+
fallbackLocale: options.fallbackLocale,
|
|
231
|
+
timeoutMs: options.timeoutMs,
|
|
232
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
233
|
+
accessToken: options.accessToken,
|
|
234
|
+
refreshToken: options.refreshToken,
|
|
235
|
+
toolId: params.toolId,
|
|
236
|
+
input: params.input,
|
|
237
|
+
preview: options.preview,
|
|
238
|
+
apply: options.apply,
|
|
239
|
+
confirm: options.confirm,
|
|
240
|
+
idempotencyKey: options.idempotencyKey,
|
|
241
|
+
});
|
|
242
|
+
const result = unwrapHostedToolResult(payload);
|
|
243
|
+
if (options.json) {
|
|
244
|
+
console.log(JSON.stringify(buildEnvelope({
|
|
245
|
+
command: params.command,
|
|
246
|
+
toolId: params.toolId,
|
|
247
|
+
resolvedContext: buildResolvedContextRecord(resolvedContext),
|
|
248
|
+
input: params.input,
|
|
249
|
+
artifacts: collectResourceArtifacts(result),
|
|
250
|
+
result,
|
|
251
|
+
}), null, 2));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
logSuccess(params.successText);
|
|
255
|
+
console.log(JSON.stringify(result, null, 2));
|
|
256
|
+
}
|
|
257
|
+
export async function runResourceList(options = {}) {
|
|
258
|
+
try {
|
|
259
|
+
const apiState = await requireApiState(options);
|
|
260
|
+
if (!apiState)
|
|
261
|
+
return;
|
|
262
|
+
const resolvedContext = await resolveResourceContext(options, apiState);
|
|
263
|
+
const input = {
|
|
264
|
+
filter: compactPayload({
|
|
265
|
+
scopeId: normalizeNonEmpty(resolvedContext.scopeId),
|
|
266
|
+
scopeResolution: options.scopeResolution,
|
|
267
|
+
name: normalizeNonEmpty(options.name),
|
|
268
|
+
resourceType: normalizeNonEmpty(options.resourceType),
|
|
269
|
+
tags: options.tag && options.tag.length > 0 ? options.tag : undefined,
|
|
270
|
+
refType: normalizeNonEmpty(options.refType),
|
|
271
|
+
refId: normalizeNonEmpty(options.refId),
|
|
272
|
+
}),
|
|
273
|
+
options: compactPayload({
|
|
274
|
+
limit: options.limit !== undefined ? toInteger(options.limit, '--limit') : undefined,
|
|
275
|
+
}),
|
|
276
|
+
};
|
|
277
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
278
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
279
|
+
tenantId: options.tenantId,
|
|
280
|
+
locale: options.locale,
|
|
281
|
+
fallbackLocale: options.fallbackLocale,
|
|
282
|
+
timeoutMs: options.timeoutMs,
|
|
283
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
284
|
+
accessToken: options.accessToken,
|
|
285
|
+
refreshToken: options.refreshToken,
|
|
286
|
+
toolId: 'agentspace.resource.list-resources',
|
|
287
|
+
input,
|
|
288
|
+
});
|
|
289
|
+
const result = unwrapHostedToolResult(payload);
|
|
290
|
+
const outputResult = options.summary ? summarizeResourceListResult(result) : result;
|
|
291
|
+
if (options.json) {
|
|
292
|
+
console.log(JSON.stringify(buildEnvelope({
|
|
293
|
+
command: 'resource.list',
|
|
294
|
+
toolId: 'agentspace.resource.list-resources',
|
|
295
|
+
resolvedContext: buildResolvedContextRecord(resolvedContext),
|
|
296
|
+
input,
|
|
297
|
+
result: outputResult,
|
|
298
|
+
}), null, 2));
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
logSuccess('Resource list 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
|
+
export async function runResourceGet(options = {}) {
|
|
310
|
+
try {
|
|
311
|
+
const apiState = await requireApiState(options);
|
|
312
|
+
if (!apiState)
|
|
313
|
+
return;
|
|
314
|
+
const resolvedContext = await resolveResourceContext(options, apiState);
|
|
315
|
+
const id = ensureResourceId(options.id);
|
|
316
|
+
const input = { id };
|
|
317
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
318
|
+
...buildGatewayOptions(options, resolvedContext),
|
|
319
|
+
tenantId: options.tenantId,
|
|
320
|
+
locale: options.locale,
|
|
321
|
+
fallbackLocale: options.fallbackLocale,
|
|
322
|
+
timeoutMs: options.timeoutMs,
|
|
323
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
324
|
+
accessToken: options.accessToken,
|
|
325
|
+
refreshToken: options.refreshToken,
|
|
326
|
+
toolId: 'agentspace.resource.get-resource',
|
|
327
|
+
input,
|
|
328
|
+
});
|
|
329
|
+
const result = unwrapHostedToolResult(payload);
|
|
330
|
+
if (options.json) {
|
|
331
|
+
console.log(JSON.stringify(buildEnvelope({
|
|
332
|
+
command: 'resource.get',
|
|
333
|
+
toolId: 'agentspace.resource.get-resource',
|
|
334
|
+
resolvedContext: buildResolvedContextRecord(resolvedContext),
|
|
335
|
+
input,
|
|
336
|
+
artifacts: collectResourceArtifacts(result),
|
|
337
|
+
result,
|
|
338
|
+
}), null, 2));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
logSuccess('Resource loaded.');
|
|
342
|
+
console.log(JSON.stringify(result, null, 2));
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
346
|
+
process.exitCode = 1;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
export async function runResourceCreate(options = {}) {
|
|
350
|
+
try {
|
|
351
|
+
const apiState = await requireApiState(options);
|
|
352
|
+
if (!apiState)
|
|
353
|
+
return;
|
|
354
|
+
const resolvedContext = await resolveResourceContext(options, apiState);
|
|
355
|
+
const seed = parseJsonSeed(options.input);
|
|
356
|
+
const name = resolveStringField(options.name, seed, 'name');
|
|
357
|
+
const resourceType = resolveStringField(options.resourceType, seed, 'resourceType');
|
|
358
|
+
if (!name)
|
|
359
|
+
throw new Error('Resource create requires --name or input.name.');
|
|
360
|
+
if (!resourceType)
|
|
361
|
+
throw new Error('Resource create requires --resource-type or input.resourceType.');
|
|
362
|
+
const input = {
|
|
363
|
+
data: compactPayload({
|
|
364
|
+
scopeId: requireScopeId(resolvedContext, seed),
|
|
365
|
+
name,
|
|
366
|
+
description: resolveStringField(options.description, seed, 'description'),
|
|
367
|
+
resourceType,
|
|
368
|
+
uri: resolveStringField(options.uri, seed, 'uri'),
|
|
369
|
+
tags: resolveStringArrayField(options.tag, seed, 'tags'),
|
|
370
|
+
refType: resolveStringField(options.refType, seed, 'refType'),
|
|
371
|
+
refId: resolveStringField(options.refId, seed, 'refId'),
|
|
372
|
+
meta: resolveUnknownField(options.meta, seed, 'meta', '--meta'),
|
|
373
|
+
}),
|
|
374
|
+
};
|
|
375
|
+
await invokeResourceTool(apiState, options, resolvedContext, {
|
|
376
|
+
command: 'resource.create',
|
|
377
|
+
toolId: 'agentspace.resource.create-resource',
|
|
378
|
+
input,
|
|
379
|
+
successText: 'Resource created.',
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
384
|
+
process.exitCode = 1;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
export async function runResourceUpdate(options = {}) {
|
|
388
|
+
try {
|
|
389
|
+
const apiState = await requireApiState(options);
|
|
390
|
+
if (!apiState)
|
|
391
|
+
return;
|
|
392
|
+
const resolvedContext = await resolveResourceContext(options, apiState);
|
|
393
|
+
const seed = parseJsonSeed(options.input);
|
|
394
|
+
const id = ensureResourceId(resolveStringField(options.id, seed, 'id'));
|
|
395
|
+
const patch = compactPayload({
|
|
396
|
+
name: resolveStringField(options.name, seed, 'name'),
|
|
397
|
+
description: resolveStringField(options.description, seed, 'description'),
|
|
398
|
+
resourceType: resolveStringField(options.resourceType, seed, 'resourceType'),
|
|
399
|
+
uri: resolveStringField(options.uri, seed, 'uri'),
|
|
400
|
+
tags: resolveStringArrayField(options.tag, seed, 'tags'),
|
|
401
|
+
refType: resolveStringField(options.refType, seed, 'refType'),
|
|
402
|
+
refId: resolveStringField(options.refId, seed, 'refId'),
|
|
403
|
+
meta: resolveUnknownField(options.meta, seed, 'meta', '--meta'),
|
|
404
|
+
});
|
|
405
|
+
if (Object.keys(patch).length === 0) {
|
|
406
|
+
throw new Error('Provide at least one resource field to update.');
|
|
407
|
+
}
|
|
408
|
+
const input = { id, patch };
|
|
409
|
+
await invokeResourceTool(apiState, options, resolvedContext, {
|
|
410
|
+
command: 'resource.update',
|
|
411
|
+
toolId: 'agentspace.resource.update-resource',
|
|
412
|
+
input,
|
|
413
|
+
successText: 'Resource updated.',
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
418
|
+
process.exitCode = 1;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
export async function runResourceDelete(options = {}) {
|
|
422
|
+
try {
|
|
423
|
+
ensureDestructiveWrite(options, 'This command deletes hosted resources.');
|
|
424
|
+
const apiState = await requireApiState(options);
|
|
425
|
+
if (!apiState)
|
|
426
|
+
return;
|
|
427
|
+
const resolvedContext = await resolveResourceContext(options, apiState);
|
|
428
|
+
const id = ensureResourceId(options.id);
|
|
429
|
+
const input = { id };
|
|
430
|
+
await invokeResourceTool(apiState, options, resolvedContext, {
|
|
431
|
+
command: 'resource.delete',
|
|
432
|
+
toolId: 'agentspace.resource.remove-resource',
|
|
433
|
+
input,
|
|
434
|
+
successText: 'Resource deleted.',
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
logError(error instanceof Error ? error.message : String(error));
|
|
439
|
+
process.exitCode = 1;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
function applyResourceContextOptions(cmd, params = {}) {
|
|
443
|
+
applyCommonOptions(cmd);
|
|
444
|
+
cmd.option('--project-id <id>', 'Project id used to resolve repo-bound resource ownership');
|
|
445
|
+
cmd.option('--project-name <name>', 'Project name used to resolve repo-bound resource ownership');
|
|
446
|
+
cmd.option('--scope-id <id>', 'Explicit scope id override for resource ownership');
|
|
447
|
+
if (params.withScopeResolution) {
|
|
448
|
+
cmd.option('--scope-resolution <mode>', 'Scope resolution policy: explicit or cascade');
|
|
449
|
+
}
|
|
450
|
+
return cmd;
|
|
451
|
+
}
|
|
452
|
+
function applyWriteGuards(cmd, params = {}) {
|
|
453
|
+
cmd.option('--preview', 'Return a validated preflight summary without executing the tool');
|
|
454
|
+
cmd.option('--apply', 'Execute the hosted write operation');
|
|
455
|
+
if (params.destructive) {
|
|
456
|
+
cmd.option('--confirm', 'Required with --apply for destructive deletes');
|
|
457
|
+
}
|
|
458
|
+
cmd.option('--idempotency-key <key>', 'Optional idempotency key for hosted writes');
|
|
459
|
+
return cmd;
|
|
460
|
+
}
|
|
461
|
+
function applyJsonSeedOption(cmd) {
|
|
462
|
+
cmd.option('--input <jsonOrFile>', 'Optional JSON object seed or @file.json');
|
|
463
|
+
return cmd;
|
|
464
|
+
}
|
|
465
|
+
export function makeResourceCommand() {
|
|
466
|
+
const cmd = new Command('resource').description('Agentspace resource sugar commands over the hosted AOPS gateway');
|
|
467
|
+
applyResourceContextOptions(cmd.command('list')
|
|
468
|
+
.description('List reusable resource shells')
|
|
469
|
+
.option('--name <text>', 'Resource name filter')
|
|
470
|
+
.option('--resource-type <type>', 'Resource type filter')
|
|
471
|
+
.option('--tag <tag>', 'Resource tag filter', collectRepeatedOption, [])
|
|
472
|
+
.option('--ref-type <type>', 'Resource refType filter')
|
|
473
|
+
.option('--ref-id <id>', 'Resource refId filter')
|
|
474
|
+
.option('--limit <n>', 'Optional item limit')
|
|
475
|
+
.option('--summary', 'Print compact resource records and omit raw meta payloads'), { withScopeResolution: true }).action(async (options) => {
|
|
476
|
+
await runResourceList(options);
|
|
477
|
+
});
|
|
478
|
+
applyResourceContextOptions(cmd.command('get')
|
|
479
|
+
.description('Get a resource by id')
|
|
480
|
+
.requiredOption('--id <id>', 'Resource id')).action(async (options) => {
|
|
481
|
+
await runResourceGet(options);
|
|
482
|
+
});
|
|
483
|
+
applyWriteGuards(applyJsonSeedOption(applyResourceContextOptions(cmd.command('create')
|
|
484
|
+
.description('Create a scope-owned resource')
|
|
485
|
+
.requiredOption('--name <text>', 'Resource name')
|
|
486
|
+
.requiredOption('--resource-type <type>', 'Resource type: document, rule, spec, link, reference, template, dataset, code, skill')
|
|
487
|
+
.option('--description <text>', 'Resource description')
|
|
488
|
+
.option('--uri <text>', 'Resource uri')
|
|
489
|
+
.option('--tag <tag>', 'Resource tag', collectRepeatedOption, [])
|
|
490
|
+
.option('--ref-type <type>', 'Optional resource refType')
|
|
491
|
+
.option('--ref-id <id>', 'Optional resource refId')
|
|
492
|
+
.option('--meta <jsonOrFile>', 'JSON meta object/array/value or @file.json')))).action(async (options) => {
|
|
493
|
+
await runResourceCreate(options);
|
|
494
|
+
});
|
|
495
|
+
applyWriteGuards(applyJsonSeedOption(applyResourceContextOptions(cmd.command('update')
|
|
496
|
+
.description('Update a resource')
|
|
497
|
+
.requiredOption('--id <id>', 'Resource id')
|
|
498
|
+
.option('--name <text>', 'Resource name')
|
|
499
|
+
.option('--resource-type <type>', 'Resource type')
|
|
500
|
+
.option('--description <text>', 'Resource description')
|
|
501
|
+
.option('--uri <text>', 'Resource uri')
|
|
502
|
+
.option('--tag <tag>', 'Resource tag', collectRepeatedOption, [])
|
|
503
|
+
.option('--ref-type <type>', 'Optional resource refType')
|
|
504
|
+
.option('--ref-id <id>', 'Optional resource refId')
|
|
505
|
+
.option('--meta <jsonOrFile>', 'JSON meta object/array/value or @file.json')))).action(async (options) => {
|
|
506
|
+
await runResourceUpdate(options);
|
|
507
|
+
});
|
|
508
|
+
applyWriteGuards(applyResourceContextOptions(cmd.command('delete')
|
|
509
|
+
.description('Delete a resource')
|
|
510
|
+
.requiredOption('--id <id>', 'Resource id')), { destructive: true }).action(async (options) => {
|
|
511
|
+
await runResourceDelete(options);
|
|
512
|
+
});
|
|
513
|
+
cmd.addHelpText('after', buildOperatorCookbook({
|
|
514
|
+
examples: [
|
|
515
|
+
'aops-cli resource create --name "Hexagen Guide" --resource-type document --apply --json',
|
|
516
|
+
'aops-cli resource list --resource-type document --summary --json',
|
|
517
|
+
'aops-cli resource update --id <resource-id> --uri https://example.test/spec --apply --json',
|
|
518
|
+
'aops-cli resource get --id <resource-id> --json',
|
|
519
|
+
],
|
|
520
|
+
guide: GUIDE_PATHS.agentspace,
|
|
521
|
+
notes: [
|
|
522
|
+
'Read-only list/get commands do not require --apply.',
|
|
523
|
+
'Use list --summary for token-efficient inventories; use get --id for full metadata.',
|
|
524
|
+
],
|
|
525
|
+
}));
|
|
526
|
+
return cmd;
|
|
527
|
+
}
|