@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,710 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { banner, logError, logInfo, logSuccess } from '@aopslabs/xf-cli-ui';
|
|
4
|
+
import { applyCommonOptions, compactPayload, normalizeNonEmpty } from '../utils/command.js';
|
|
5
|
+
import { buildAgentContextHeaders, invokeHostedToolWithApiState, parseJsonInput, requireApiState, unwrapHostedToolResult, } from '../utils/agent-gateway.js';
|
|
6
|
+
import { promptInput } from '../utils/prompts.js';
|
|
7
|
+
function augmentAgentInvokeErrorMessage(toolId, message) {
|
|
8
|
+
const normalized = String(message ?? '').toLowerCase();
|
|
9
|
+
if (normalized.includes('apply_required')) {
|
|
10
|
+
return `${message}\nRetry with --apply because ${toolId} is a guarded write tool.`;
|
|
11
|
+
}
|
|
12
|
+
if (normalized.includes('confirmation_required')) {
|
|
13
|
+
return `${message}\nRetry with --confirm after verifying the destructive action is intended.`;
|
|
14
|
+
}
|
|
15
|
+
return message;
|
|
16
|
+
}
|
|
17
|
+
function asRecord(value) {
|
|
18
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
19
|
+
? value
|
|
20
|
+
: null;
|
|
21
|
+
}
|
|
22
|
+
function asStringArray(value) {
|
|
23
|
+
return Array.isArray(value)
|
|
24
|
+
? value.map((entry) => normalizeNonEmpty(entry)).filter((entry) => Boolean(entry))
|
|
25
|
+
: [];
|
|
26
|
+
}
|
|
27
|
+
function parsePositiveInteger(value) {
|
|
28
|
+
const parsed = Number.parseInt(value, 10);
|
|
29
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
30
|
+
throw new Error('Expected a positive integer.');
|
|
31
|
+
}
|
|
32
|
+
return parsed;
|
|
33
|
+
}
|
|
34
|
+
function extractTagValue(tags, prefix) {
|
|
35
|
+
const match = tags.find((tag) => tag.toLowerCase().startsWith(prefix));
|
|
36
|
+
if (!match)
|
|
37
|
+
return undefined;
|
|
38
|
+
return normalizeNonEmpty(match.slice(prefix.length));
|
|
39
|
+
}
|
|
40
|
+
function compactTool(tool, options = {}) {
|
|
41
|
+
const tags = asStringArray(tool.tags);
|
|
42
|
+
const policy = asRecord(tool.policy);
|
|
43
|
+
const safety = asRecord(policy?.safety);
|
|
44
|
+
const links = asRecord(tool.links);
|
|
45
|
+
const examples = asStringArray(tool.examples);
|
|
46
|
+
const toolId = normalizeNonEmpty(tool.toolId) ??
|
|
47
|
+
normalizeNonEmpty(tool.id) ??
|
|
48
|
+
normalizeNonEmpty(tool.operationId) ??
|
|
49
|
+
'(unknown-tool)';
|
|
50
|
+
const title = normalizeNonEmpty(tool.title);
|
|
51
|
+
const summary = normalizeNonEmpty(tool.summary);
|
|
52
|
+
const guard = compactPayload({
|
|
53
|
+
apply: safety?.applyRequired,
|
|
54
|
+
confirm: safety?.confirmationRequired,
|
|
55
|
+
destructive: safety?.destructive,
|
|
56
|
+
});
|
|
57
|
+
return compactPayload({
|
|
58
|
+
id: toolId,
|
|
59
|
+
domain: normalizeNonEmpty(tool.domain),
|
|
60
|
+
op: normalizeNonEmpty(tool.operationId),
|
|
61
|
+
title,
|
|
62
|
+
summary: summary && summary !== title ? summary : undefined,
|
|
63
|
+
resource: extractTagValue(tags, 'resource:'),
|
|
64
|
+
kind: extractTagValue(tags, 'kind:'),
|
|
65
|
+
action: extractTagValue(tags, 'action:'),
|
|
66
|
+
effect: normalizeNonEmpty(tool.sideEffect),
|
|
67
|
+
schema: normalizeNonEmpty(tool.inputSchemaRef),
|
|
68
|
+
guard: Object.keys(guard).length > 0 ? guard : undefined,
|
|
69
|
+
source: normalizeNonEmpty(tool.defaultSourceId),
|
|
70
|
+
detail: normalizeNonEmpty(links?.detail),
|
|
71
|
+
invoke: normalizeNonEmpty(links?.invoke),
|
|
72
|
+
example: options.examples ? examples[0] : undefined,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function toolMatchesQuery(tool, query) {
|
|
76
|
+
const tags = asStringArray(tool.tags);
|
|
77
|
+
const haystack = [
|
|
78
|
+
tool.toolId,
|
|
79
|
+
tool.id,
|
|
80
|
+
tool.domain,
|
|
81
|
+
tool.operationId,
|
|
82
|
+
tool.title,
|
|
83
|
+
tool.summary,
|
|
84
|
+
tool.description,
|
|
85
|
+
tool.inputSchemaRef,
|
|
86
|
+
tool.outputSchemaRef,
|
|
87
|
+
tool.sideEffect,
|
|
88
|
+
tool.defaultSourceId,
|
|
89
|
+
...tags,
|
|
90
|
+
]
|
|
91
|
+
.map((value) => normalizeNonEmpty(value)?.toLowerCase())
|
|
92
|
+
.filter((value) => Boolean(value))
|
|
93
|
+
.join('\n');
|
|
94
|
+
return haystack.includes(query);
|
|
95
|
+
}
|
|
96
|
+
function summarizeRecommendedTool(value) {
|
|
97
|
+
const tool = asRecord(value);
|
|
98
|
+
if (!tool)
|
|
99
|
+
return undefined;
|
|
100
|
+
return compactPayload({
|
|
101
|
+
toolId: normalizeNonEmpty(tool.toolId),
|
|
102
|
+
title: normalizeNonEmpty(tool.title),
|
|
103
|
+
summary: normalizeNonEmpty(tool.summary),
|
|
104
|
+
reason: normalizeNonEmpty(tool.reason),
|
|
105
|
+
operationKind: normalizeNonEmpty(tool.operationKind),
|
|
106
|
+
resource: normalizeNonEmpty(tool.resource),
|
|
107
|
+
safety: normalizeNonEmpty(tool.safety),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function summarizeResource(value) {
|
|
111
|
+
const resource = asRecord(value);
|
|
112
|
+
if (!resource)
|
|
113
|
+
return undefined;
|
|
114
|
+
return compactPayload({
|
|
115
|
+
resourceId: normalizeNonEmpty(resource.resourceId),
|
|
116
|
+
title: normalizeNonEmpty(resource.title),
|
|
117
|
+
summary: normalizeNonEmpty(resource.summary),
|
|
118
|
+
kind: normalizeNonEmpty(resource.kind),
|
|
119
|
+
toolCount: resource.toolCount,
|
|
120
|
+
operationKinds: asStringArray(resource.operationKinds),
|
|
121
|
+
sampleToolIds: asStringArray(resource.sampleToolIds).slice(0, 6),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function resourceMatchesQuery(resource, query) {
|
|
125
|
+
const haystack = [
|
|
126
|
+
resource.resourceId,
|
|
127
|
+
resource.title,
|
|
128
|
+
resource.summary,
|
|
129
|
+
resource.kind,
|
|
130
|
+
...asStringArray(resource.operationKinds),
|
|
131
|
+
...asStringArray(resource.sampleToolIds),
|
|
132
|
+
]
|
|
133
|
+
.map((value) => normalizeNonEmpty(value)?.toLowerCase())
|
|
134
|
+
.filter((value) => Boolean(value))
|
|
135
|
+
.join('\n');
|
|
136
|
+
return haystack.includes(query);
|
|
137
|
+
}
|
|
138
|
+
function buildAgentToolsSummary(params) {
|
|
139
|
+
const { payload, tools, originalToolCount, matchedToolCount, domain, q, limit, examples } = params;
|
|
140
|
+
const flow = asRecord(payload.flow);
|
|
141
|
+
const discovery = asRecord(payload.discovery);
|
|
142
|
+
const routes = asRecord(discovery?.routes);
|
|
143
|
+
const provenance = asRecord(discovery?.provenance);
|
|
144
|
+
const referenceDomain = asRecord(discovery?.referenceDomain) ?? asRecord(provenance?.referenceDomain);
|
|
145
|
+
const rawResources = Array.isArray(referenceDomain?.humanReadableResources)
|
|
146
|
+
? referenceDomain.humanReadableResources
|
|
147
|
+
: [];
|
|
148
|
+
const resources = rawResources
|
|
149
|
+
.map((entry) => asRecord(entry))
|
|
150
|
+
.filter((entry) => Boolean(entry))
|
|
151
|
+
.filter((entry) => q ? resourceMatchesQuery(entry, q) : true)
|
|
152
|
+
.map((entry) => summarizeResource(entry))
|
|
153
|
+
.filter((entry) => Boolean(entry));
|
|
154
|
+
const recommendedFirstTools = (Array.isArray(referenceDomain?.recommendedFirstTools)
|
|
155
|
+
? referenceDomain.recommendedFirstTools
|
|
156
|
+
: [])
|
|
157
|
+
.map((entry) => summarizeRecommendedTool(entry))
|
|
158
|
+
.filter((entry) => Boolean(entry))
|
|
159
|
+
.filter((entry) => {
|
|
160
|
+
if (!q)
|
|
161
|
+
return true;
|
|
162
|
+
return Object.values(entry)
|
|
163
|
+
.map((value) => normalizeNonEmpty(value)?.toLowerCase())
|
|
164
|
+
.filter((value) => Boolean(value))
|
|
165
|
+
.join('\n')
|
|
166
|
+
.includes(q);
|
|
167
|
+
})
|
|
168
|
+
.slice(0, 8);
|
|
169
|
+
return compactPayload({
|
|
170
|
+
ok: payload.ok,
|
|
171
|
+
catalogVersion: payload.catalogVersion,
|
|
172
|
+
generatedAt: payload.generatedAt,
|
|
173
|
+
partial: payload.partial,
|
|
174
|
+
domain: domain ?? normalizeNonEmpty(referenceDomain?.domain),
|
|
175
|
+
counts: {
|
|
176
|
+
total: originalToolCount,
|
|
177
|
+
matched: matchedToolCount,
|
|
178
|
+
returned: tools.length,
|
|
179
|
+
resources: resources.length,
|
|
180
|
+
},
|
|
181
|
+
filters: compactPayload({ domain, q, limit }),
|
|
182
|
+
flow: flow
|
|
183
|
+
? compactPayload({
|
|
184
|
+
summary: normalizeNonEmpty(flow.summary),
|
|
185
|
+
routes: asRecord(flow.routes),
|
|
186
|
+
})
|
|
187
|
+
: undefined,
|
|
188
|
+
discovery: compactPayload({
|
|
189
|
+
toolCatalog: normalizeNonEmpty(routes?.toolCatalog),
|
|
190
|
+
toolDetailTemplate: normalizeNonEmpty(routes?.toolDetailTemplate),
|
|
191
|
+
invokeTemplate: normalizeNonEmpty(routes?.invokeTemplate),
|
|
192
|
+
rawDiscoveryDocument: normalizeNonEmpty(routes?.rawDiscoveryDocument),
|
|
193
|
+
rawOpenapi: normalizeNonEmpty(routes?.rawOpenapi),
|
|
194
|
+
}),
|
|
195
|
+
resources,
|
|
196
|
+
recommendedFirstTools,
|
|
197
|
+
tools: tools.map((tool) => compactTool(tool, { examples })),
|
|
198
|
+
next: {
|
|
199
|
+
narrow: 'aops-cli agent tools --domain <domain> --q <keyword> --summary --json',
|
|
200
|
+
schema: 'aops-cli agent schema --tool <toolId> --json',
|
|
201
|
+
invoke: "aops-cli agent invoke --tool <toolId> --input '@payload.json' --preview|--apply --json",
|
|
202
|
+
},
|
|
203
|
+
errors: Array.isArray(payload.errors) && payload.errors.length > 0 ? payload.errors : undefined,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
function selectAgentTools(tools, options) {
|
|
207
|
+
const q = normalizeNonEmpty(options.q)?.toLowerCase();
|
|
208
|
+
const limit = Number.isFinite(options.limit) && options.limit && options.limit > 0
|
|
209
|
+
? options.limit
|
|
210
|
+
: undefined;
|
|
211
|
+
const normalizedTools = tools
|
|
212
|
+
.map((entry) => asRecord(entry))
|
|
213
|
+
.filter((entry) => Boolean(entry));
|
|
214
|
+
const matchedTools = q
|
|
215
|
+
? normalizedTools.filter((tool) => toolMatchesQuery(tool, q))
|
|
216
|
+
: normalizedTools;
|
|
217
|
+
const selectedTools = typeof limit === 'number' ? matchedTools.slice(0, limit) : matchedTools;
|
|
218
|
+
return {
|
|
219
|
+
selectedTools,
|
|
220
|
+
matchedToolCount: matchedTools.length,
|
|
221
|
+
q,
|
|
222
|
+
limit,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function schemaType(schema) {
|
|
226
|
+
const type = schema.type;
|
|
227
|
+
if (Array.isArray(type)) {
|
|
228
|
+
return type.map((entry) => normalizeNonEmpty(entry)).filter(Boolean).join('|') || undefined;
|
|
229
|
+
}
|
|
230
|
+
const explicitType = normalizeNonEmpty(type);
|
|
231
|
+
if (explicitType)
|
|
232
|
+
return explicitType;
|
|
233
|
+
if (Array.isArray(schema.enum))
|
|
234
|
+
return 'enum';
|
|
235
|
+
if (Object.prototype.hasOwnProperty.call(schema, 'const'))
|
|
236
|
+
return 'const';
|
|
237
|
+
for (const key of ['oneOf', 'anyOf', 'allOf']) {
|
|
238
|
+
const variants = schema[key];
|
|
239
|
+
if (Array.isArray(variants))
|
|
240
|
+
return `${key}(${variants.length})`;
|
|
241
|
+
}
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
function summarizeAdditionalProperties(value) {
|
|
245
|
+
if (typeof value === 'boolean')
|
|
246
|
+
return value;
|
|
247
|
+
const schema = asRecord(value);
|
|
248
|
+
return schema ? schemaType(schema) ?? 'schema' : undefined;
|
|
249
|
+
}
|
|
250
|
+
function schemaHasProperties(schema) {
|
|
251
|
+
const properties = asRecord(schema.properties);
|
|
252
|
+
return Boolean(properties && Object.keys(properties).length > 0);
|
|
253
|
+
}
|
|
254
|
+
function isFlexibleObjectSchema(schema) {
|
|
255
|
+
return !schemaHasProperties(schema) && (schema.additionalProperties === true ||
|
|
256
|
+
Boolean(asRecord(schema.additionalProperties)));
|
|
257
|
+
}
|
|
258
|
+
function isOpaqueInputSchema(schema) {
|
|
259
|
+
if (isFlexibleObjectSchema(schema))
|
|
260
|
+
return true;
|
|
261
|
+
const properties = asRecord(schema.properties);
|
|
262
|
+
if (!properties)
|
|
263
|
+
return false;
|
|
264
|
+
return ['data', 'input', 'patch', 'payload'].some((key) => {
|
|
265
|
+
const child = asRecord(properties[key]);
|
|
266
|
+
return child ? isFlexibleObjectSchema(child) : false;
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
function summarizeEnum(value) {
|
|
270
|
+
if (!Array.isArray(value))
|
|
271
|
+
return undefined;
|
|
272
|
+
return value.slice(0, 12).map((entry) => {
|
|
273
|
+
if (entry === null || ['string', 'number', 'boolean'].includes(typeof entry))
|
|
274
|
+
return entry;
|
|
275
|
+
return String(entry);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
function collectSchemaFields(params) {
|
|
279
|
+
if (params.depth > 8)
|
|
280
|
+
return;
|
|
281
|
+
const properties = asRecord(params.schema.properties);
|
|
282
|
+
if (properties) {
|
|
283
|
+
for (const [key, rawChild] of Object.entries(properties)) {
|
|
284
|
+
const child = asRecord(rawChild);
|
|
285
|
+
if (!child)
|
|
286
|
+
continue;
|
|
287
|
+
const childPath = params.path ? `${params.path}.${key}` : key;
|
|
288
|
+
const childRequired = params.required.has(key);
|
|
289
|
+
const childRequiredSet = new Set(asStringArray(child.required));
|
|
290
|
+
const description = normalizeNonEmpty(child.description);
|
|
291
|
+
const defaultValue = Object.prototype.hasOwnProperty.call(child, 'default')
|
|
292
|
+
? child.default
|
|
293
|
+
: undefined;
|
|
294
|
+
params.fields.push(compactPayload({
|
|
295
|
+
path: childPath,
|
|
296
|
+
type: schemaType(child),
|
|
297
|
+
required: childRequired,
|
|
298
|
+
format: normalizeNonEmpty(child.format),
|
|
299
|
+
description,
|
|
300
|
+
enum: summarizeEnum(child.enum),
|
|
301
|
+
const: Object.prototype.hasOwnProperty.call(child, 'const') ? child.const : undefined,
|
|
302
|
+
default: defaultValue,
|
|
303
|
+
additionalProperties: summarizeAdditionalProperties(child.additionalProperties),
|
|
304
|
+
}));
|
|
305
|
+
collectSchemaFields({
|
|
306
|
+
schema: child,
|
|
307
|
+
path: childPath,
|
|
308
|
+
required: childRequiredSet,
|
|
309
|
+
fields: params.fields,
|
|
310
|
+
depth: params.depth + 1,
|
|
311
|
+
});
|
|
312
|
+
const items = asRecord(child.items);
|
|
313
|
+
if (items) {
|
|
314
|
+
collectSchemaFields({
|
|
315
|
+
schema: items,
|
|
316
|
+
path: `${childPath}[]`,
|
|
317
|
+
required: new Set(asStringArray(items.required)),
|
|
318
|
+
fields: params.fields,
|
|
319
|
+
depth: params.depth + 1,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
for (const key of ['oneOf', 'anyOf', 'allOf']) {
|
|
325
|
+
const variants = params.schema[key];
|
|
326
|
+
if (!Array.isArray(variants))
|
|
327
|
+
continue;
|
|
328
|
+
params.fields.push(compactPayload({
|
|
329
|
+
path: params.path || '$',
|
|
330
|
+
type: `${key}(${variants.length})`,
|
|
331
|
+
}));
|
|
332
|
+
for (const [index, rawVariant] of variants.slice(0, 4).entries()) {
|
|
333
|
+
const variant = asRecord(rawVariant);
|
|
334
|
+
if (!variant)
|
|
335
|
+
continue;
|
|
336
|
+
collectSchemaFields({
|
|
337
|
+
schema: variant,
|
|
338
|
+
path: params.path ? `${params.path}.${key}[${index}]` : `${key}[${index}]`,
|
|
339
|
+
required: new Set(asStringArray(variant.required)),
|
|
340
|
+
fields: params.fields,
|
|
341
|
+
depth: params.depth + 1,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function buildAgentSchemaSummary(params) {
|
|
347
|
+
const tool = asRecord(params.payload.tool);
|
|
348
|
+
const rootRequired = asStringArray(params.inputJsonSchema.required);
|
|
349
|
+
const fields = [];
|
|
350
|
+
collectSchemaFields({
|
|
351
|
+
schema: params.inputJsonSchema,
|
|
352
|
+
path: '',
|
|
353
|
+
required: new Set(rootRequired),
|
|
354
|
+
fields,
|
|
355
|
+
depth: 0,
|
|
356
|
+
});
|
|
357
|
+
const domain = normalizeNonEmpty(tool?.domain) ??
|
|
358
|
+
normalizeNonEmpty(params.toolId.split('.')[0]);
|
|
359
|
+
const opaque = isOpaqueInputSchema(params.inputJsonSchema);
|
|
360
|
+
const returnedFields = fields.slice(0, 80);
|
|
361
|
+
return compactPayload({
|
|
362
|
+
toolId: params.toolId,
|
|
363
|
+
title: normalizeNonEmpty(tool?.title),
|
|
364
|
+
operationId: normalizeNonEmpty(tool?.operationId),
|
|
365
|
+
domain,
|
|
366
|
+
schemaSummary: compactPayload({
|
|
367
|
+
rootType: schemaType(params.inputJsonSchema),
|
|
368
|
+
required: rootRequired,
|
|
369
|
+
additionalProperties: summarizeAdditionalProperties(params.inputJsonSchema.additionalProperties),
|
|
370
|
+
opaque,
|
|
371
|
+
fieldCount: fields.length,
|
|
372
|
+
returnedFieldCount: returnedFields.length,
|
|
373
|
+
truncated: fields.length > returnedFields.length,
|
|
374
|
+
fields: returnedFields,
|
|
375
|
+
}),
|
|
376
|
+
next: compactPayload({
|
|
377
|
+
fullSchema: `aops-cli agent schema --tool ${params.toolId} --json`,
|
|
378
|
+
openapi: domain ? `aops-cli agent openapi --domain ${domain} --json` : undefined,
|
|
379
|
+
detail: `GET /api/agent/tools/${params.toolId}`,
|
|
380
|
+
invoke: `aops-cli agent invoke --tool ${params.toolId} --input @payload.json --preview|--apply --json`,
|
|
381
|
+
fallback: opaque
|
|
382
|
+
? [
|
|
383
|
+
'If this summary is opaque, inspect OpenAPI for the operation requestBody schema.',
|
|
384
|
+
'If OpenAPI is also opaque, inspect the domain kit/Zod source before raw invoke payload authoring.',
|
|
385
|
+
'For routine sugar use, prefer the matching command --help surface.',
|
|
386
|
+
]
|
|
387
|
+
: undefined,
|
|
388
|
+
}),
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
export async function runAgentTools(options = {}) {
|
|
392
|
+
const interactive = !options.yes && !options.json;
|
|
393
|
+
const apiState = await requireApiState(options);
|
|
394
|
+
if (!apiState)
|
|
395
|
+
return;
|
|
396
|
+
const domain = normalizeNonEmpty(options.domain)?.toLowerCase();
|
|
397
|
+
const query = domain ? `?domain=${encodeURIComponent(domain)}` : '';
|
|
398
|
+
const path = `/api/agent/tools${query}`;
|
|
399
|
+
let headers;
|
|
400
|
+
try {
|
|
401
|
+
headers = await buildAgentContextHeaders(options);
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
405
|
+
logError(message);
|
|
406
|
+
process.exitCode = 1;
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (interactive) {
|
|
410
|
+
banner('AOPS Agent Tools');
|
|
411
|
+
logInfo(`API: ${apiState.baseUrl}`);
|
|
412
|
+
if (domain)
|
|
413
|
+
logInfo(`Domain filter: ${domain}`);
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
const payload = await apiState.client.fetchJson(path, {
|
|
417
|
+
method: 'GET',
|
|
418
|
+
headers,
|
|
419
|
+
timeoutMs: options.timeoutMs,
|
|
420
|
+
});
|
|
421
|
+
const tools = Array.isArray(payload.tools) ? payload.tools : [];
|
|
422
|
+
const originalToolCount = tools.length;
|
|
423
|
+
const { selectedTools, matchedToolCount, q, limit } = selectAgentTools(tools, options);
|
|
424
|
+
if (options.json) {
|
|
425
|
+
if (options.summary) {
|
|
426
|
+
console.log(JSON.stringify(buildAgentToolsSummary({
|
|
427
|
+
payload,
|
|
428
|
+
tools: selectedTools,
|
|
429
|
+
originalToolCount,
|
|
430
|
+
matchedToolCount,
|
|
431
|
+
domain,
|
|
432
|
+
q,
|
|
433
|
+
limit,
|
|
434
|
+
examples: options.examples,
|
|
435
|
+
}), null, 2));
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const shouldFilter = Boolean(q) || typeof limit === 'number';
|
|
439
|
+
console.log(JSON.stringify(shouldFilter
|
|
440
|
+
? {
|
|
441
|
+
...payload,
|
|
442
|
+
filters: compactPayload({ domain, q, limit }),
|
|
443
|
+
toolCount: {
|
|
444
|
+
total: originalToolCount,
|
|
445
|
+
matched: matchedToolCount,
|
|
446
|
+
returned: selectedTools.length,
|
|
447
|
+
},
|
|
448
|
+
tools: selectedTools,
|
|
449
|
+
}
|
|
450
|
+
: payload, null, 2));
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const errors = Array.isArray(payload.errors) ? payload.errors : [];
|
|
454
|
+
const catalogVersion = typeof payload.catalogVersion === 'string' ? payload.catalogVersion : 'unknown';
|
|
455
|
+
const flow = (payload.flow &&
|
|
456
|
+
typeof payload.flow === 'object' &&
|
|
457
|
+
!Array.isArray(payload.flow)) ? payload.flow : null;
|
|
458
|
+
logSuccess(`Tools: ${selectedTools.length}${selectedTools.length === originalToolCount ? '' : `/${originalToolCount}`} (catalog: ${catalogVersion})`);
|
|
459
|
+
if (q)
|
|
460
|
+
logInfo(`Query: ${q}`);
|
|
461
|
+
if (typeof limit === 'number')
|
|
462
|
+
logInfo(`Limit: ${limit}`);
|
|
463
|
+
const flowSummary = flow && typeof flow.summary === 'string'
|
|
464
|
+
? flow.summary
|
|
465
|
+
: undefined;
|
|
466
|
+
if (flowSummary) {
|
|
467
|
+
logInfo(`Flow: ${flowSummary}`);
|
|
468
|
+
}
|
|
469
|
+
for (const raw of selectedTools) {
|
|
470
|
+
const tool = raw;
|
|
471
|
+
const toolId = normalizeNonEmpty(tool.toolId) ??
|
|
472
|
+
normalizeNonEmpty(tool.id) ??
|
|
473
|
+
normalizeNonEmpty(tool.operationId) ??
|
|
474
|
+
'(unknown-tool)';
|
|
475
|
+
const title = normalizeNonEmpty(tool.title) ??
|
|
476
|
+
normalizeNonEmpty(tool.name) ??
|
|
477
|
+
normalizeNonEmpty(tool.summary) ??
|
|
478
|
+
normalizeNonEmpty(tool.description);
|
|
479
|
+
const sourceId = normalizeNonEmpty(tool.sourceId) ?? normalizeNonEmpty(tool.domain);
|
|
480
|
+
const suffix = [
|
|
481
|
+
sourceId ? `source=${sourceId}` : undefined,
|
|
482
|
+
title ? title : undefined,
|
|
483
|
+
]
|
|
484
|
+
.filter(Boolean)
|
|
485
|
+
.join(' | ');
|
|
486
|
+
console.log(`- ${toolId}${suffix ? ` :: ${suffix}` : ''}`);
|
|
487
|
+
}
|
|
488
|
+
if (errors.length > 0) {
|
|
489
|
+
logInfo('Source errors:');
|
|
490
|
+
for (const err of errors) {
|
|
491
|
+
console.log(`- ${JSON.stringify(err)}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (options.summary) {
|
|
495
|
+
logInfo('Next: inspect one exact input contract with `aops-cli agent schema --tool <toolId> --json`.');
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
catch (error) {
|
|
499
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
500
|
+
logError(`Failed to fetch agent tools: ${message}`);
|
|
501
|
+
process.exitCode = 1;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
export async function runAgentInvoke(options = {}) {
|
|
505
|
+
const interactive = !options.yes && !options.json;
|
|
506
|
+
const apiState = await requireApiState(options);
|
|
507
|
+
if (!apiState)
|
|
508
|
+
return;
|
|
509
|
+
let toolId = normalizeNonEmpty(options.tool)?.toLowerCase();
|
|
510
|
+
if (!toolId && interactive) {
|
|
511
|
+
toolId = normalizeNonEmpty(await promptInput({ message: 'Tool id:' }))?.toLowerCase();
|
|
512
|
+
}
|
|
513
|
+
if (!toolId) {
|
|
514
|
+
logError('Missing tool id. Provide --tool <id>.');
|
|
515
|
+
process.exitCode = 1;
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
let input;
|
|
519
|
+
try {
|
|
520
|
+
input = parseJsonInput(options.input, 'input');
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
524
|
+
logError(message);
|
|
525
|
+
process.exitCode = 1;
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
if (interactive) {
|
|
529
|
+
banner('AOPS Agent Invoke');
|
|
530
|
+
logInfo(`API: ${apiState.baseUrl}`);
|
|
531
|
+
logInfo(`Tool: ${toolId}`);
|
|
532
|
+
}
|
|
533
|
+
try {
|
|
534
|
+
const payload = await invokeHostedToolWithApiState(apiState, {
|
|
535
|
+
...options,
|
|
536
|
+
toolId,
|
|
537
|
+
input,
|
|
538
|
+
});
|
|
539
|
+
if (options.json) {
|
|
540
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
logSuccess('Tool invocation completed.');
|
|
544
|
+
console.log(JSON.stringify(unwrapHostedToolResult(payload), null, 2));
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
548
|
+
logError(`Failed to invoke tool ${toolId}: ${augmentAgentInvokeErrorMessage(toolId, message)}`);
|
|
549
|
+
process.exitCode = 1;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
export async function runAgentOpenApi(options = {}) {
|
|
553
|
+
const interactive = !options.yes && !options.json;
|
|
554
|
+
const apiState = await requireApiState(options);
|
|
555
|
+
if (!apiState)
|
|
556
|
+
return;
|
|
557
|
+
const domain = normalizeNonEmpty(options.domain)?.toLowerCase();
|
|
558
|
+
const query = domain ? `?domain=${encodeURIComponent(domain)}` : '';
|
|
559
|
+
const path = `/api/agent/openapi.json${query}`;
|
|
560
|
+
if (interactive) {
|
|
561
|
+
banner('AOPS Agent OpenAPI');
|
|
562
|
+
logInfo(`API: ${apiState.baseUrl}`);
|
|
563
|
+
if (domain)
|
|
564
|
+
logInfo(`Domain filter: ${domain}`);
|
|
565
|
+
}
|
|
566
|
+
try {
|
|
567
|
+
const payload = await apiState.client.fetchJson(path, {
|
|
568
|
+
method: 'GET',
|
|
569
|
+
timeoutMs: options.timeoutMs,
|
|
570
|
+
});
|
|
571
|
+
const pretty = JSON.stringify(payload, null, 2);
|
|
572
|
+
const outPath = normalizeNonEmpty(options.out);
|
|
573
|
+
if (outPath) {
|
|
574
|
+
writeFileSync(outPath, `${pretty}\n`, 'utf8');
|
|
575
|
+
if (!options.json)
|
|
576
|
+
logSuccess(`Wrote ${outPath}`);
|
|
577
|
+
}
|
|
578
|
+
console.log(pretty);
|
|
579
|
+
}
|
|
580
|
+
catch (error) {
|
|
581
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
582
|
+
logError(`Failed to generate OpenAPI: ${message}`);
|
|
583
|
+
process.exitCode = 1;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
export async function runAgentSchema(options = {}) {
|
|
587
|
+
const interactive = !options.yes && !options.json;
|
|
588
|
+
const apiState = await requireApiState(options);
|
|
589
|
+
if (!apiState)
|
|
590
|
+
return;
|
|
591
|
+
const toolId = normalizeNonEmpty(options.tool)?.toLowerCase();
|
|
592
|
+
if (!toolId) {
|
|
593
|
+
logError('Missing tool id. Provide --tool <id>.');
|
|
594
|
+
process.exitCode = 1;
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
const path = `/api/agent/tools/${encodeURIComponent(toolId)}`;
|
|
598
|
+
if (interactive) {
|
|
599
|
+
banner('AOPS Agent Schema');
|
|
600
|
+
logInfo(`API: ${apiState.baseUrl}`);
|
|
601
|
+
logInfo(`Tool: ${toolId}`);
|
|
602
|
+
}
|
|
603
|
+
try {
|
|
604
|
+
const payload = await apiState.client.fetchJson(path, {
|
|
605
|
+
method: 'GET',
|
|
606
|
+
timeoutMs: options.timeoutMs,
|
|
607
|
+
});
|
|
608
|
+
const inputJsonSchema = payload?.tool?.inputJsonSchema;
|
|
609
|
+
const inputSchemaRecord = asRecord(inputJsonSchema);
|
|
610
|
+
if (!inputSchemaRecord) {
|
|
611
|
+
logError(`No input schema is published for ${toolId}. The tool's kit may not expose a per-operation input schema yet.`);
|
|
612
|
+
process.exitCode = 1;
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const result = options.summary
|
|
616
|
+
? buildAgentSchemaSummary({ toolId, payload, inputJsonSchema: inputSchemaRecord })
|
|
617
|
+
: { toolId, inputJsonSchema };
|
|
618
|
+
const pretty = JSON.stringify(result, null, 2);
|
|
619
|
+
const outPath = normalizeNonEmpty(options.out);
|
|
620
|
+
if (outPath) {
|
|
621
|
+
writeFileSync(outPath, `${pretty}\n`, 'utf8');
|
|
622
|
+
if (!options.json)
|
|
623
|
+
logSuccess(`Wrote ${outPath}`);
|
|
624
|
+
}
|
|
625
|
+
if (options.json) {
|
|
626
|
+
console.log(pretty);
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
logSuccess('Input schema fetched.');
|
|
630
|
+
console.log(pretty);
|
|
631
|
+
}
|
|
632
|
+
catch (error) {
|
|
633
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
634
|
+
logError(`Failed to fetch schema for ${toolId}: ${message}`);
|
|
635
|
+
process.exitCode = 1;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
export function makeAgentCommand() {
|
|
639
|
+
const cmd = new Command('agent').description('Primary operator plane for federated tool discovery and invoke');
|
|
640
|
+
applyCommonOptions(cmd
|
|
641
|
+
.command('tools')
|
|
642
|
+
.description('List federated tools from the canonical operator plane (/api/agent/tools)')
|
|
643
|
+
.option('--domain <id>', 'Filter by domain id (e.g. docman)')
|
|
644
|
+
.option('--q <text>', 'Client-side search over tool id, title, summary, tags, resource, and kind')
|
|
645
|
+
.option('--limit <n>', 'Limit returned tools after filtering', parsePositiveInteger)
|
|
646
|
+
.option('--summary', 'Print a compact, token-efficient catalog summary (especially useful with --json)')
|
|
647
|
+
.option('--examples', 'Include first invoke example in --summary output')
|
|
648
|
+
.option('--tenant-id <id>', 'Tenant id header (x-tenant-id)')
|
|
649
|
+
.option('--locale <locale>', 'Locale header (x-locale)')
|
|
650
|
+
.option('--fallback-locale <locale>', 'Fallback locale header (x-fallback-locale)')
|
|
651
|
+
.option('--scope-id <id>', 'Canonical owner scope override')
|
|
652
|
+
.option('--scope-resolution <mode>', 'Owner scope read mode: explicit or cascade')
|
|
653
|
+
.option('--project-id <id>', 'Project id used to resolve owner scope from the active AOPS context')
|
|
654
|
+
.option('--project-name <name>', 'Project name from repo-local .aops/aops.config.json for owner-scope resolution')
|
|
655
|
+
.action(async (options) => {
|
|
656
|
+
await runAgentTools(options);
|
|
657
|
+
}), { withProject: false });
|
|
658
|
+
applyCommonOptions(cmd
|
|
659
|
+
.command('invoke')
|
|
660
|
+
.description('Invoke a tool via the canonical operator plane (/api/agent/tools/{toolId}/invoke)')
|
|
661
|
+
.option('--tool <id>', 'Tool id')
|
|
662
|
+
.option('--source-id <id>', 'Optional source id override')
|
|
663
|
+
.option('--input <json>', 'JSON input payload or @file.json')
|
|
664
|
+
.option('--preview', 'Return a validated preflight summary without executing the tool')
|
|
665
|
+
.option('--apply', 'Explicitly allow guarded write operations')
|
|
666
|
+
.option('--confirm', 'Explicitly confirm destructive operations')
|
|
667
|
+
.option('--idempotency-key <key>', 'Optional guarded-write idempotency key')
|
|
668
|
+
.option('--tenant-id <id>', 'Tenant id header (x-tenant-id)')
|
|
669
|
+
.option('--locale <locale>', 'Locale header (x-locale)')
|
|
670
|
+
.option('--fallback-locale <locale>', 'Fallback locale header (x-fallback-locale)')
|
|
671
|
+
.option('--scope-id <id>', 'Canonical owner scope override')
|
|
672
|
+
.option('--scope-resolution <mode>', 'Owner scope read mode: explicit or cascade')
|
|
673
|
+
.option('--project-id <id>', 'Project id used to resolve owner scope from the active AOPS context')
|
|
674
|
+
.option('--project-name <name>', 'Project name from repo-local .aops/aops.config.json for owner-scope resolution')
|
|
675
|
+
.action(async (options) => {
|
|
676
|
+
await runAgentInvoke(options);
|
|
677
|
+
}), { withProject: false });
|
|
678
|
+
applyCommonOptions(cmd
|
|
679
|
+
.command('openapi')
|
|
680
|
+
.description('Generate OpenAPI from the canonical federated tool catalog')
|
|
681
|
+
.option('--domain <id>', 'Filter OpenAPI by domain')
|
|
682
|
+
.option('--out <path>', 'Write output to file')
|
|
683
|
+
.action(async (options) => {
|
|
684
|
+
await runAgentOpenApi(options);
|
|
685
|
+
}), { withProject: false });
|
|
686
|
+
applyCommonOptions(cmd
|
|
687
|
+
.command('schema')
|
|
688
|
+
.description("Print the live JSON Schema for one tool's input contract — use this before authoring --input payloads")
|
|
689
|
+
.option('--tool <id>', 'Tool id (e.g. docman.document.create)')
|
|
690
|
+
.option('--summary', 'Print a compact flattened field summary and fallback ladder')
|
|
691
|
+
.option('--out <path>', 'Write output to file')
|
|
692
|
+
.action(async (options) => {
|
|
693
|
+
await runAgentSchema(options);
|
|
694
|
+
}), { withProject: false });
|
|
695
|
+
cmd.addHelpText('after', `
|
|
696
|
+
Examples:
|
|
697
|
+
aops-cli agent tools --domain docman
|
|
698
|
+
aops-cli agent tools --domain agentspace --summary --json
|
|
699
|
+
aops-cli agent tools --domain agentspace --q memory --limit 20 --summary --json
|
|
700
|
+
aops-cli agent tools --domain agentspace --q resource.create --summary --examples --json
|
|
701
|
+
aops-cli agent tools --domain docman --scope-id <scope-id>
|
|
702
|
+
aops-cli agent invoke --tool docman.document-group.list --project-id <project-id> --input '{"query":{"limit":10}}'
|
|
703
|
+
aops-cli agent invoke --tool docman.document-group.create --scope-id <scope-id> --apply --input '{"data":{"groupUid":"api-guides","title":"API Guides"}}'
|
|
704
|
+
aops-cli agent invoke --tool inventory.unit.create --project-id <project-id> --preview --input '{"unitTypeUid":"length","unitUid":"mm"}'
|
|
705
|
+
aops-cli agent invoke --tool inventory.unit.create --project-id <project-id> --apply --idempotency-key inventory.unit.create:seed-1 --input '{"unitTypeUid":"length","unitUid":"mm","nameMl":{"en":"Millimeter"}}'
|
|
706
|
+
aops-cli agent schema --tool docman.document.create --summary --json
|
|
707
|
+
aops-cli agent openapi --out ./openapi.json
|
|
708
|
+
`);
|
|
709
|
+
return cmd;
|
|
710
|
+
}
|