@frontera-sdk/cli 1.52.39 → 1.52.41
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/README.md +9 -0
- package/package.json +6 -4
- package/src/adopt.ts +6 -2
- package/src/api/apps-api.ts +86 -4
- package/src/api/blueprint-authoring-api.ts +35 -11
- package/src/api/dataset-api.ts +29 -0
- package/src/api/governed-action-api.ts +90 -2
- package/src/api/platform-api.ts +87 -2
- package/src/api/workflow-api.ts +33 -2
- package/src/app-contract.ts +156 -0
- package/src/app-lock.ts +125 -0
- package/src/args.ts +14 -3
- package/src/auth-verify.ts +10 -0
- package/src/automation-template.ts +12 -1
- package/src/blueprint/action-rules.ts +516 -0
- package/src/blueprint/action-semantic-fit.ts +205 -0
- package/src/blueprint/compile.ts +51 -2
- package/src/blueprint/diff.ts +34 -2
- package/src/blueprint/metric-query.ts +215 -0
- package/src/blueprint/metric-rules.ts +122 -0
- package/src/blueprint/object-sets.ts +116 -0
- package/src/blueprint/ontology-edit-plan.ts +49 -5
- package/src/blueprint/projection.ts +24 -1
- package/src/blueprint/scaffold.ts +84 -42
- package/src/commands/action/available.ts +1 -1
- package/src/commands/action/criteria-refusal.ts +84 -0
- package/src/commands/action/decide.ts +5 -2
- package/src/commands/action/deploy.ts +13 -4
- package/src/commands/action/list.ts +134 -19
- package/src/commands/action/requests.ts +34 -6
- package/src/commands/action/submit.ts +28 -13
- package/src/commands/agent/draft-changes.ts +1 -1
- package/src/commands/agent/index-commands.ts +69 -7
- package/src/commands/agent/resolve.ts +2 -0
- package/src/commands/app/checks.ts +44 -0
- package/src/commands/app/deploy.ts +243 -60
- package/src/commands/app/deployments.ts +97 -0
- package/src/commands/app/dev.ts +103 -11
- package/src/commands/app/init.ts +36 -3
- package/src/commands/app/promote.ts +45 -19
- package/src/commands/app/pull.ts +3 -1
- package/src/commands/app/rollback.ts +46 -0
- package/src/commands/app/sdk.ts +54 -8
- package/src/commands/app/unpin.ts +27 -0
- package/src/commands/app/versions.ts +1 -1
- package/src/commands/automation/bindings.ts +4 -2
- package/src/commands/automation/build-entry.ts +4 -1
- package/src/commands/automation/index-commands.ts +3 -1
- package/src/commands/automation/pull.ts +6 -1
- package/src/commands/automation/run.ts +34 -9
- package/src/commands/blueprint/bind.ts +2 -1
- package/src/commands/blueprint/declarative.ts +332 -32
- package/src/commands/blueprint/editable.ts +3 -3
- package/src/commands/blueprint/get.ts +6 -2
- package/src/commands/blueprint/grants.ts +64 -10
- package/src/commands/blueprint/metric.ts +108 -0
- package/src/commands/blueprint/object-sets.ts +71 -0
- package/src/commands/blueprint/query.ts +155 -31
- package/src/commands/dataset/index-commands.ts +156 -7
- package/src/commands/knowledge/index-commands.ts +122 -20
- package/src/commands/local/check.ts +657 -44
- package/src/commands/local/data.ts +33 -12
- package/src/commands/local/dev.ts +876 -89
- package/src/commands/local/docs-mcp.ts +10 -18
- package/src/commands/local/index-commands.ts +300 -63
- package/src/commands/local/init.ts +18 -5
- package/src/commands/local/key.ts +0 -3
- package/src/commands/local/providers.ts +0 -7
- package/src/commands/local/remove.ts +116 -0
- package/src/commands/local/schema.ts +3 -4
- package/src/commands/local/sdk-refresh.ts +59 -0
- package/src/commands/local/snapshot.ts +100 -0
- package/src/commands/local/sync-request.ts +321 -14
- package/src/commands/local/sync.ts +103 -6
- package/src/commands/mcp/serve.ts +34 -0
- package/src/commands/registry.ts +54 -10
- package/src/commands/types.ts +29 -0
- package/src/commands/workflow/archive.ts +46 -0
- package/src/commands/workflow/get.ts +2 -1
- package/src/commands/workflow/index-commands.ts +5 -0
- package/src/commands/workflow/push.ts +49 -2
- package/src/commands/workflow/run.ts +65 -7
- package/src/commands/workflow/runs.ts +9 -6
- package/src/commands/workflow/webhook-test.ts +166 -0
- package/src/config.ts +43 -6
- package/src/dev-broker.ts +52 -0
- package/src/exit.ts +103 -4
- package/src/flag-help.ts +77 -17
- package/src/forge/claude-commands.ts +11 -6
- package/src/forge/claude-skills.ts +4 -4
- package/src/forge/touches.ts +15 -12
- package/src/function-outside-imports.ts +89 -0
- package/src/harness.ts +42 -24
- package/src/heal.ts +113 -2
- package/src/kit.ts +1 -1
- package/src/local/fix-words.ts +12 -0
- package/src/local/function-bundle-recovery.ts +775 -0
- package/src/local/local-actions.ts +103 -10
- package/src/local/local-agent-action-grants.ts +210 -0
- package/src/local/local-agent-checks.ts +232 -0
- package/src/local/local-agent-grants.ts +29 -7
- package/src/local/local-agent-lean-plugins.ts +68 -0
- package/src/local/local-agent-missing-tools.ts +68 -0
- package/src/local/local-agent-name.ts +27 -0
- package/src/local/local-app-code.ts +191 -0
- package/src/local/local-app-dev-files.ts +186 -0
- package/src/local/local-app-dev-session.ts +88 -0
- package/src/local/local-app-lock-install.ts +114 -0
- package/src/local/local-app-pulled.ts +167 -0
- package/src/local/local-app-restore.ts +111 -0
- package/src/local/local-app-runtime.ts +68 -0
- package/src/local/local-app-sdk-paths.ts +149 -0
- package/src/local/local-app-sdk.ts +509 -0
- package/src/local/local-applied.ts +212 -22
- package/src/local/local-apply-history.ts +84 -0
- package/src/local/local-apply-summary.ts +86 -0
- package/src/local/local-apply-watchdog.ts +95 -0
- package/src/local/local-apps.ts +181 -8
- package/src/local/local-blueprint-errors.ts +198 -0
- package/src/local/local-blueprint-outline.ts +31 -12
- package/src/local/local-blueprint-schemas.ts +582 -0
- package/src/local/local-build-inputs.ts +48 -0
- package/src/local/local-build-summary.ts +495 -28
- package/src/local/local-case-evidence.ts +120 -0
- package/src/local/local-case-not-run.ts +153 -0
- package/src/local/local-chat-apps.ts +93 -16
- package/src/local/local-check-inherited.ts +83 -0
- package/src/local/local-cities.ts +89 -0
- package/src/local/local-component-health.ts +119 -0
- package/src/local/local-control.ts +34 -7
- package/src/local/local-db-snapshot.ts +348 -0
- package/src/local/local-dev-references.ts +347 -36
- package/src/local/local-dev-sync.ts +141 -12
- package/src/local/local-docker.ts +35 -1
- package/src/local/local-docs-search.ts +1 -1
- package/src/local/local-docs.ts +281 -2
- package/src/local/local-empty-workflows.ts +92 -0
- package/src/local/local-env.ts +16 -1
- package/src/local/local-file-checks.ts +104 -0
- package/src/local/local-function-ids.ts +141 -0
- package/src/local/local-function-recovery.ts +141 -0
- package/src/local/local-function-state.ts +87 -0
- package/src/local/local-keys.ts +7 -5
- package/src/local/local-knowledge-documents.ts +1 -1
- package/src/local/local-knowledge-ingestion.ts +225 -0
- package/src/local/local-knowledge-uploads.ts +217 -0
- package/src/local/local-lessons.ts +1 -1
- package/src/local/local-library.ts +1 -1
- package/src/local/local-media-placeholders.ts +182 -0
- package/src/local/local-media-sets.ts +90 -10
- package/src/local/local-model-parameters.ts +89 -0
- package/src/local/local-object-sets.ts +18 -6
- package/src/local/local-operating.ts +35 -1
- package/src/local/local-org-settings.ts +206 -8
- package/src/local/local-orphans.ts +321 -0
- package/src/local/local-personas.ts +296 -0
- package/src/local/local-portability.ts +143 -18
- package/src/local/local-ports.ts +99 -7
- package/src/local/local-project-notices.ts +234 -0
- package/src/local/local-project-secrets.ts +133 -0
- package/src/local/local-project.ts +12 -0
- package/src/local/local-provider-refusal.ts +66 -0
- package/src/local/local-request-evidence.ts +112 -0
- package/src/local/local-runtime-health.ts +123 -0
- package/src/local/local-runtime-history.ts +50 -0
- package/src/local/local-runtime-target.ts +42 -0
- package/src/local/local-sample-data.ts +141 -0
- package/src/local/local-sample-remake.ts +138 -0
- package/src/local/local-scaffold.ts +336 -53
- package/src/local/local-schema-check.ts +148 -0
- package/src/local/local-schemas.ts +742 -25
- package/src/local/local-secret-carry.ts +107 -0
- package/src/local/local-secrets.ts +41 -11
- package/src/local/local-seed.ts +102 -26
- package/src/local/local-stand-ins.ts +3 -3
- package/src/local/local-state.ts +43 -2
- package/src/local/local-studio-server.ts +170 -7
- package/src/local/local-supervisor.ts +44 -6
- package/src/local/local-sync-merge.ts +1 -1
- package/src/local/local-sync-names.ts +2 -0
- package/src/local/local-sync-plan.ts +19 -8
- package/src/local/local-sync-push.ts +15 -12
- package/src/local/local-sync-refs.ts +49 -3
- package/src/local/local-sync-remote.ts +349 -38
- package/src/local/local-sync-snapshot.ts +18 -13
- package/src/local/local-synthetic-data.ts +2116 -99
- package/src/local/local-test-baseline.ts +113 -0
- package/src/local/local-test-cases.ts +76 -1
- package/src/local/local-test-runner.ts +582 -91
- package/src/local/local-test-runs.ts +13 -5
- package/src/local/local-vendored-sdk.ts +183 -0
- package/src/local/local-workflow-state.ts +16 -3
- package/src/local/local-workflow-tests.ts +482 -0
- package/src/local/local-workspace-grants.ts +81 -0
- package/src/main.ts +50 -9
- package/src/mcp/a11y-scan.ts +55 -0
- package/src/mcp/browser/ax-snapshot.ts +181 -0
- package/src/mcp/browser/credentials.ts +78 -0
- package/src/mcp/browser/frames.ts +336 -0
- package/src/mcp/browser/headless-session.ts +413 -0
- package/src/mcp/browser/headless-tab.ts +575 -0
- package/src/mcp/browser/keys.ts +70 -0
- package/src/mcp/browser/page-scripts.ts +129 -0
- package/src/mcp/browser/wait.ts +73 -0
- package/src/mcp/forge-link.ts +126 -0
- package/src/mcp/headless.ts +199 -0
- package/src/mcp/mcp-apps.ts +435 -0
- package/src/mcp/mcp-chat.ts +226 -0
- package/src/mcp/mcp-cli.ts +53 -0
- package/src/mcp/mcp-protocol.ts +122 -0
- package/src/mcp/mcp-runtime.ts +113 -0
- package/src/mcp/mcp-server.ts +108 -0
- package/src/mcp/mcp-traces.ts +409 -0
- package/src/mcp/page-observation.ts +193 -0
- package/src/mcp/tools/agent-tools.ts +700 -0
- package/src/mcp/tools/app-tools.ts +241 -0
- package/src/mcp/tools/browser-tools.ts +310 -0
- package/src/mcp/tools/docs-tools.ts +32 -0
- package/src/mcp/tools/project-tools.ts +205 -0
- package/src/mcp/tools/test-tools.ts +339 -0
- package/src/mcp/tools/workflow-tools.ts +611 -0
- package/src/output.ts +1 -1
- package/src/pack.ts +8 -3
- package/src/packaging.ts +1 -1
- package/src/project-bootstrap.ts +107 -4
- package/src/project-context.ts +18 -1
- package/src/project.ts +27 -2
- package/src/provenance.ts +25 -0
- package/src/render-evidence.ts +65 -7
- package/src/scopes.ts +1 -1
- package/src/template.ts +14 -8
- package/src/templates/next-app-files.ts +35 -6
- package/src/templates/next-skills.ts +61 -27
- package/src/vendor/kit-assets.json +6 -6
- package/src/vendor/sdk-sources.json +17 -14
package/README.md
CHANGED
|
@@ -112,6 +112,10 @@ project) and `frontera app init` (scaffold a new app) are different commands.
|
|
|
112
112
|
|
|
113
113
|
`0` success · `1` transient · `2` usage · `3` conflict · `4` auth. Branch on
|
|
114
114
|
them rather than on message text.
|
|
115
|
+
Governed Action conflicts (a stale record version or approval, a record that
|
|
116
|
+
already has an open request of the Action, a moved approval step) exit `3`,
|
|
117
|
+
by code or by the refusal's `reason`; an idempotency key reused for another
|
|
118
|
+
request exits `2` (`exit.ts`).
|
|
115
119
|
|
|
116
120
|
## Project configuration
|
|
117
121
|
|
|
@@ -137,6 +141,11 @@ gitignored `.frontera/state.json`. Existing projects that already use
|
|
|
137
141
|
Next Apps consume the published `@frontera-sdk/core` and
|
|
138
142
|
`@frontera-sdk/blueprint` packages. Existing Vite Apps retain vendored SDK
|
|
139
143
|
source; `frontera app sdk sync` refreshes only that generated tree.
|
|
144
|
+
On a local runtime started from a platform checkout (source mode),
|
|
145
|
+
`frontera app sdk use-local` packs the checkout's `@frontera-sdk/*` packages
|
|
146
|
+
into the App's `vendor/frontera-sdk/` and points `package.json` at them; commit
|
|
147
|
+
that folder, and `--npm` switches back. It is a local development command and
|
|
148
|
+
is kept out of the customer CLI reference.
|
|
140
149
|
|
|
141
150
|
## What `app init` does
|
|
142
151
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontera-sdk/cli",
|
|
3
|
-
"version": "1.52.
|
|
3
|
+
"version": "1.52.41",
|
|
4
4
|
"description": "The frontera CLI — scaffold, pull, save and deploy Frontera apps and automations.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"frontera",
|
|
@@ -40,14 +40,16 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@anthropic-ai/claude-agent-sdk": "^0.3.251",
|
|
42
42
|
"@faker-js/faker": "10.6.0",
|
|
43
|
-
"@frontera-sdk/core": "1.52.
|
|
44
|
-
"@frontera-sdk/functions": "1.52.
|
|
43
|
+
"@frontera-sdk/core": "1.52.41",
|
|
44
|
+
"@frontera-sdk/functions": "1.52.41",
|
|
45
45
|
"ai": "^6.0.116",
|
|
46
|
+
"axe-core": "4.12.1",
|
|
46
47
|
"gray-matter": "^4.0.3",
|
|
48
|
+
"playwright-core": "1.63.0",
|
|
47
49
|
"yaml": "^2.9.0"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
|
-
"@frontera-sdk/forge-contracts": "1.52.
|
|
52
|
+
"@frontera-sdk/forge-contracts": "1.52.41",
|
|
51
53
|
"@types/bun": "^1.3.14",
|
|
52
54
|
"typescript": "^5.9.3"
|
|
53
55
|
}
|
package/src/adopt.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { join } from 'node:path'
|
|
|
3
3
|
|
|
4
4
|
import { UsageError } from './errors'
|
|
5
5
|
import { nextSkillFiles } from './templates/next-skills'
|
|
6
|
+
import { SDK_RANGE } from './templates/next-app-files'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Turn an existing Next.js project into a Frontera App.
|
|
@@ -167,8 +168,8 @@ export interface AdoptionPlan {
|
|
|
167
168
|
* project rather than by reading this list.
|
|
168
169
|
*/
|
|
169
170
|
const REQUIRED_DEPENDENCIES: Record<string, string> = {
|
|
170
|
-
'@frontera-sdk/blueprint':
|
|
171
|
-
'@frontera-sdk/core':
|
|
171
|
+
'@frontera-sdk/blueprint': SDK_RANGE,
|
|
172
|
+
'@frontera-sdk/core': SDK_RANGE,
|
|
172
173
|
'@tanstack/react-query': '^5.90.21',
|
|
173
174
|
'class-variance-authority': '^0.7.1',
|
|
174
175
|
clsx: '^2.1.1',
|
|
@@ -193,6 +194,8 @@ const NEXT_CONFIG_KEYS = [
|
|
|
193
194
|
['trailingSlash', 'true'],
|
|
194
195
|
['images', '{ unoptimized: true }'],
|
|
195
196
|
['transpilePackages', "['@frontera-sdk/core', '@frontera-sdk/blueprint', '@frontera-sdk/agents']"],
|
|
197
|
+
// Without it `next dev` rewrites AGENTS.md on every run, and a deploy refuses the build as stale.
|
|
198
|
+
['agentRules', 'false'],
|
|
196
199
|
] as const
|
|
197
200
|
|
|
198
201
|
export function planAdoption(target: AdoptionTarget): AdoptionPlan {
|
|
@@ -322,6 +325,7 @@ const nextConfig: NextConfig = {
|
|
|
322
325
|
trailingSlash: true,
|
|
323
326
|
images: { unoptimized: true },
|
|
324
327
|
transpilePackages: ['@frontera-sdk/core', '@frontera-sdk/blueprint', '@frontera-sdk/agents'],
|
|
328
|
+
agentRules: false,
|
|
325
329
|
}
|
|
326
330
|
|
|
327
331
|
export default nextConfig
|
package/src/api/apps-api.ts
CHANGED
|
@@ -27,6 +27,49 @@ export interface AppVersionSummary {
|
|
|
27
27
|
} | null
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export interface DeploymentCheck {
|
|
31
|
+
id: 'build' | 'render' | 'contract' | 'a11y'
|
|
32
|
+
label: string
|
|
33
|
+
status: 'passed' | 'failed' | 'missing'
|
|
34
|
+
detail: string
|
|
35
|
+
required: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface DeploymentRow {
|
|
39
|
+
id: string
|
|
40
|
+
label: string | null
|
|
41
|
+
producer: { kind: 'person' | 'workspace-key' | 'agent-key'; id: string; name: string | null }
|
|
42
|
+
session: { id: string; harness: string | null } | null
|
|
43
|
+
branch: string | null
|
|
44
|
+
commit: string | null
|
|
45
|
+
dirty: boolean
|
|
46
|
+
commitAuthor: string | null
|
|
47
|
+
changeRequestId: string | null
|
|
48
|
+
createdAt: string
|
|
49
|
+
productionAt: string | null
|
|
50
|
+
staged: boolean
|
|
51
|
+
pruned: { at: string; restorable: boolean } | null
|
|
52
|
+
/** `production`, `branch:<name>`, `session:<id>`. */
|
|
53
|
+
serves: string[]
|
|
54
|
+
renderEvidence: Record<string, unknown>
|
|
55
|
+
fileCount: number
|
|
56
|
+
totalBytes: number
|
|
57
|
+
url: string | null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface DeploymentLedger {
|
|
61
|
+
app: { id: string; slug: string; displayName: string }
|
|
62
|
+
production: {
|
|
63
|
+
deployment: string | null
|
|
64
|
+
label: string | null
|
|
65
|
+
pinned: { at: string; by: string | null; byName: string | null; reason: string | null; undoTo: string | null } | null
|
|
66
|
+
}
|
|
67
|
+
previews: Array<{ kind: 'branch' | 'session'; name: string; deployment: string | null; label: string | null; updatedAt: string; url: string | null }>
|
|
68
|
+
policy: { protectedApps: boolean; keysMayPromote: boolean; requiredChecks: string[] }
|
|
69
|
+
canPromote: boolean
|
|
70
|
+
deployments: DeploymentRow[]
|
|
71
|
+
}
|
|
72
|
+
|
|
30
73
|
export interface AppTokenResponse {
|
|
31
74
|
token: string
|
|
32
75
|
expiresAt: number
|
|
@@ -129,12 +172,16 @@ export class AppsApi {
|
|
|
129
172
|
}
|
|
130
173
|
|
|
131
174
|
publish(appId: string, args: {
|
|
132
|
-
|
|
175
|
+
/** An optional release label, unique per App. The deployment gets its own id. */
|
|
176
|
+
label?: string | null
|
|
177
|
+
/** Go live once the required checks pass (`--prod`); otherwise a preview. */
|
|
178
|
+
prod?: boolean
|
|
179
|
+
/** With `prod`: a staged production deployment, served by nothing until promoted. */
|
|
180
|
+
stage?: boolean
|
|
133
181
|
parentVersion?: string | null
|
|
134
182
|
dist: Uint8Array
|
|
135
183
|
source: Uint8Array
|
|
136
184
|
manifest?: unknown
|
|
137
|
-
promote: boolean
|
|
138
185
|
/** §4.4 — whether this tree had been rendered since its last source change. */
|
|
139
186
|
renderEvidence?: unknown
|
|
140
187
|
/** Recorded build/package metadata; never trusted for authorization. */
|
|
@@ -143,20 +190,30 @@ export class AppsApi {
|
|
|
143
190
|
thumbnail?: Uint8Array | null
|
|
144
191
|
}) {
|
|
145
192
|
const form = new FormData()
|
|
146
|
-
form.set('
|
|
193
|
+
if (args.label) form.set('label', args.label)
|
|
194
|
+
form.set('prod', args.prod ? 'true' : 'false')
|
|
195
|
+
if (args.prod && args.stage) form.set('stage', 'true')
|
|
147
196
|
if (args.parentVersion) form.set('parentVersion', args.parentVersion)
|
|
148
197
|
form.set('dist', new Blob([args.dist], { type: 'application/gzip' }), 'dist.tgz')
|
|
149
198
|
form.set('source', new Blob([args.source], { type: 'application/gzip' }), 'src.tgz')
|
|
150
199
|
if (args.manifest) form.set('manifest', JSON.stringify(args.manifest))
|
|
151
|
-
form.set('promote', args.promote ? 'true' : 'false')
|
|
152
200
|
if (args.renderEvidence) form.set('renderEvidence', JSON.stringify(args.renderEvidence))
|
|
153
201
|
if (args.provenance) form.set('provenance', JSON.stringify(args.provenance))
|
|
154
202
|
if (args.thumbnail && args.thumbnail.byteLength > 0) {
|
|
155
203
|
form.set('thumbnail', new Blob([args.thumbnail], { type: 'image/png' }), 'thumbnail.png')
|
|
156
204
|
}
|
|
157
205
|
return this.multipart<{
|
|
206
|
+
/** The deployment's id (`dpl_…`); `version` is the same, for older services. */
|
|
207
|
+
deployment?: string
|
|
158
208
|
version: string
|
|
209
|
+
label?: string | null
|
|
159
210
|
promoted: boolean
|
|
211
|
+
staged?: boolean
|
|
212
|
+
/** Asked for production and refused: the permission, the pin, or a required check. */
|
|
213
|
+
promoteRefused?: { message: string; code: string | null; checks?: DeploymentCheck[] }
|
|
214
|
+
branch?: string
|
|
215
|
+
branchUrl?: string
|
|
216
|
+
sessionUrl?: string
|
|
160
217
|
fileCount: number
|
|
161
218
|
totalBytes: number
|
|
162
219
|
/** Where a person opens this exact build — composed by the service,
|
|
@@ -208,6 +265,31 @@ export class AppsApi {
|
|
|
208
265
|
)
|
|
209
266
|
}
|
|
210
267
|
|
|
268
|
+
/** The deployment ledger: production and its pin, the preview links, every deployment and what serves it. */
|
|
269
|
+
deployments(appId: string): Promise<DeploymentLedger> {
|
|
270
|
+
return this.client.request<DeploymentLedger>(`/v1/platform-apps/${appId}/deployments`)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
checks(appId: string, deployment: string): Promise<{ deployment: string; checks: DeploymentCheck[] }> {
|
|
274
|
+
return this.client.request(`/v1/platform-apps/${appId}/deployments/${encodeURIComponent(deployment)}/checks`)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
promote(appId: string, body: { deployment: string; force?: boolean; reason?: string }) {
|
|
278
|
+
return this.client.request<{ promoted: string; label: string | null; checks: DeploymentCheck[]; forced: string[]; liveUrl?: string }>(`/v1/platform-apps/${appId}/promote`, { method: 'POST', body })
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
rollback(appId: string, body: { deployment?: string; reason: string }) {
|
|
282
|
+
return this.client.request<{ from: string | null; fromLabel?: string | null; to: string; label: string | null; pinned: true }>(`/v1/platform-apps/${appId}/rollback`, { method: 'POST', body })
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
undoRollback(appId: string) {
|
|
286
|
+
return this.client.request<{ restored: string | null; label: string | null; pinned: false }>(`/v1/platform-apps/${appId}/rollback/undo`, { method: 'POST', body: {} })
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
unpin(appId: string, reason: string) {
|
|
290
|
+
return this.client.request<{ pinned: false; production: string | null; productionLabel?: string | null }>(`/v1/platform-apps/${appId}/unpin`, { method: 'POST', body: { reason } })
|
|
291
|
+
}
|
|
292
|
+
|
|
211
293
|
deploy(appId: string, version: string) {
|
|
212
294
|
return this.client.request<{ deployedVersion: string }>(`/v1/platform-apps/${appId}/deploy`, {
|
|
213
295
|
method: 'POST',
|
|
@@ -96,6 +96,8 @@ export class BlueprintAuthoringApi {
|
|
|
96
96
|
throw new CliError(payload?.message ?? `${res.status} ${text.slice(0, 200)}`, {
|
|
97
97
|
code: (payload?.code as string) ?? 'FAILURE',
|
|
98
98
|
hint: detail ?? 'frontera blueprint status',
|
|
99
|
+
// Kept whole: `plan` reads a refusal's reason from it (`withServiceActionChecks`).
|
|
100
|
+
...(payload?.details !== undefined ? { details: payload.details } : {}),
|
|
99
101
|
})
|
|
100
102
|
}
|
|
101
103
|
|
|
@@ -456,14 +458,29 @@ export class BlueprintAuthoringApi {
|
|
|
456
458
|
return this.call('/v1/blueprint/actions?view=draft')
|
|
457
459
|
}
|
|
458
460
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
+
/**
|
|
462
|
+
* `inherited`: the Action is as the workspace it was pulled from holds it, so
|
|
463
|
+
* a semantic-type conflict it has is the workspace's. The local runtime then
|
|
464
|
+
* takes it as the workspace runs it; any other service ignores it.
|
|
465
|
+
*/
|
|
466
|
+
createAction(action: Record<string, unknown>, expectedRevision: number, inherited = false) {
|
|
467
|
+
return this.call('/v1/blueprint/actions', { method: 'POST', body: { expectedRevision, action, ...(inherited ? { inherited } : {}) } })
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* The checks a create or update of this Action runs, against the current
|
|
472
|
+
* draft, with nothing written (`POST /v1/blueprint/actions/check`). Create
|
|
473
|
+
* or update is the service's call, by the action's apiName. A refusal
|
|
474
|
+
* throws as the write would.
|
|
475
|
+
*/
|
|
476
|
+
checkAction(action: Record<string, unknown>, inherited = false): Promise<{ operation: 'create' | 'update' }> {
|
|
477
|
+
return this.call('/v1/blueprint/actions/check', { method: 'POST', body: { action, ...(inherited ? { inherited } : {}) } })
|
|
461
478
|
}
|
|
462
479
|
|
|
463
|
-
updateAction(apiName: string, action: Record<string, unknown>, expectedRevision: number) {
|
|
480
|
+
updateAction(apiName: string, action: Record<string, unknown>, expectedRevision: number, inherited = false) {
|
|
464
481
|
return this.call(`/v1/blueprint/actions/${encodeURIComponent(apiName)}`, {
|
|
465
482
|
method: 'PUT',
|
|
466
|
-
body: { expectedRevision, action },
|
|
483
|
+
body: { expectedRevision, action, ...(inherited ? { inherited } : {}) },
|
|
467
484
|
})
|
|
468
485
|
}
|
|
469
486
|
|
|
@@ -498,22 +515,24 @@ export class BlueprintAuthoringApi {
|
|
|
498
515
|
return this.call('/v1/blueprint/org-workspaces')
|
|
499
516
|
}
|
|
500
517
|
|
|
501
|
-
|
|
518
|
+
/** The organization's Agents, unpublished ones too (`published`), each with its slug (`agentId`). */
|
|
519
|
+
orgAgents(): Promise<Array<{ id?: string; name?: string; agentId?: string; slug?: string; published?: boolean }>> {
|
|
502
520
|
return this.call('/v1/blueprint/org-agents')
|
|
503
521
|
}
|
|
504
522
|
|
|
505
|
-
workspaceGrants(workspaceId: string): Promise<Array<{ objectTypeApiName?: string }>> {
|
|
523
|
+
workspaceGrants(workspaceId: string): Promise<Array<{ objectTypeApiName?: string; permissions?: string[] }>> {
|
|
506
524
|
return this.call(`/v1/blueprint/grants/workspace/${encodeURIComponent(workspaceId)}`)
|
|
507
525
|
}
|
|
508
526
|
|
|
509
|
-
agentGrants(agentId: string): Promise<Array<{ objectTypeApiName?: string }>> {
|
|
527
|
+
agentGrants(agentId: string): Promise<Array<{ objectTypeApiName?: string; permissions?: string[] }>> {
|
|
510
528
|
return this.call(`/v1/blueprint/grants/agent/${encodeURIComponent(agentId)}`)
|
|
511
529
|
}
|
|
512
530
|
|
|
513
|
-
|
|
531
|
+
/** `permissions` sets the grant's whole list (`read`, `read_sensitive`); left out, it is `read`. */
|
|
532
|
+
grantWorkspace(workspaceId: string, objectTypeApiName: string, permissions?: string[]) {
|
|
514
533
|
return this.call('/v1/blueprint/grants/workspace', {
|
|
515
534
|
method: 'POST',
|
|
516
|
-
body: { workspaceId, objectTypeApiName },
|
|
535
|
+
body: { workspaceId, objectTypeApiName, ...(permissions ? { permissions } : {}) },
|
|
517
536
|
})
|
|
518
537
|
}
|
|
519
538
|
|
|
@@ -524,10 +543,15 @@ export class BlueprintAuthoringApi {
|
|
|
524
543
|
)
|
|
525
544
|
}
|
|
526
545
|
|
|
527
|
-
|
|
546
|
+
/**
|
|
547
|
+
* `permissions` is the grant's list (`read`, `read_sensitive`, `act`); left out, it is `read`.
|
|
548
|
+
* A re-grant keeps an `act` the grant already holds: the platform takes it away only when
|
|
549
|
+
* the request names it in `removePermissions`, as `local dev` does.
|
|
550
|
+
*/
|
|
551
|
+
grantAgent(agentId: string, objectTypeApiName: string, permissions?: string[]) {
|
|
528
552
|
return this.call('/v1/blueprint/grants/agent', {
|
|
529
553
|
method: 'POST',
|
|
530
|
-
body: { agentId, objectTypeApiName },
|
|
554
|
+
body: { agentId, objectTypeApiName, ...(permissions ? { permissions } : {}) },
|
|
531
555
|
})
|
|
532
556
|
}
|
|
533
557
|
|
package/src/api/dataset-api.ts
CHANGED
|
@@ -327,6 +327,35 @@ export class DatasetApi {
|
|
|
327
327
|
)
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
/**
|
|
331
|
+
* A new revision of a managed (file) dataset from a CSV whose columns now
|
|
332
|
+
* allow empty values the current revision refuses: `POST
|
|
333
|
+
* /datasets/:id/revisions/from-file`, multipart with the CSV as `file` and
|
|
334
|
+
* the revision it follows as `expectedRevision`. The service allows only a
|
|
335
|
+
* widening of nullability; an added, dropped or retyped column (or a key
|
|
336
|
+
* column turned nullable) is a 409 naming it, and a file that changes
|
|
337
|
+
* nothing a 409 `DATASET_REVISION_UNCHANGED`. A runtime that predates the
|
|
338
|
+
* route answers 404, said here in words.
|
|
339
|
+
*/
|
|
340
|
+
async reviseFromFile(datasetId: string, path: string, expectedRevision: number): Promise<DatasetSummary> {
|
|
341
|
+
const form = new FormData()
|
|
342
|
+
form.append('file', new Blob([readFileSync(path)]), basename(path))
|
|
343
|
+
form.append('expectedRevision', String(expectedRevision))
|
|
344
|
+
try {
|
|
345
|
+
return await this.call<DatasetSummary>(`/v1/data-integration/datasets/${encodeURIComponent(datasetId)}/revisions/from-file`, { form })
|
|
346
|
+
} catch (err) {
|
|
347
|
+
// An unknown route may answer 404 in words, not JSON.
|
|
348
|
+
const unknownRoute = err instanceof SyntaxError || (err instanceof CliError && (err.code === 'NOT_FOUND' || /not found|404/i.test(err.message)) && !/dataset/i.test(err.message))
|
|
349
|
+
if (unknownRoute) {
|
|
350
|
+
throw new CliError('This Frontera release cannot cut a new revision of a file dataset.', {
|
|
351
|
+
code: 'NOT_SUPPORTED',
|
|
352
|
+
hint: 'Keep the columns as the dataset has them, or declare a column `nullable: true` in its definition before its first load. On a local runtime, `frontera local reset` creates every dataset again from its definition.',
|
|
353
|
+
})
|
|
354
|
+
}
|
|
355
|
+
throw err
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
330
359
|
createBlank(payload: {
|
|
331
360
|
apiName: string
|
|
332
361
|
displayName: string
|
|
@@ -39,6 +39,41 @@ export interface ActionRequestSummary {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/** A row of `GET /v1/blueprint/governed-actions/discovery`. */
|
|
42
|
+
/**
|
|
43
|
+
* The refusal for invoking an Action with no deployment (409, `details.reason:
|
|
44
|
+
* ACTION_NOT_DEPLOYED`), as "Action <name> isn't deployed: <why>", or null
|
|
45
|
+
* when the body is some other refusal. `ACTION_FORBIDDEN` is a genuine
|
|
46
|
+
* authorization refusal and is left to the credential handling.
|
|
47
|
+
*/
|
|
48
|
+
export function notDeployedError(details: unknown, path: string): CliError | null {
|
|
49
|
+
const d = (details && typeof details === 'object' ? details : null) as { reason?: unknown; deploymentStatus?: unknown; readinessReason?: unknown; details?: unknown } | null
|
|
50
|
+
const inner = d && d.reason === undefined && d.details && typeof d.details === 'object' ? (d.details as typeof d) : d
|
|
51
|
+
if (!inner || inner.reason !== 'ACTION_NOT_DEPLOYED') return null
|
|
52
|
+
const name = decodeURIComponent(/\/actions\/([^/?]+)/.exec(path)?.[1] ?? 'it')
|
|
53
|
+
const why = typeof inner.readinessReason === 'string' ? inner.readinessReason : typeof inner.deploymentStatus === 'string' ? `its deployment is ${inner.deploymentStatus}` : 'it has no active deployment'
|
|
54
|
+
return new CliError(`Action ${name} isn't deployed: ${why}`, {
|
|
55
|
+
code: 'ACTION_NOT_DEPLOYED',
|
|
56
|
+
hint: name === 'it' ? 'frontera action list shows each Action’s deployment and why it cannot run' : `\`frontera action deploy ${name}\` builds its write path; \`frontera action list\` shows why each Action cannot run (in a local project, \`frontera local dev\` deploys it)`,
|
|
57
|
+
details: { reason: 'ACTION_NOT_DEPLOYED', action: name === 'it' ? null : name, deploymentStatus: inner.deploymentStatus ?? null, readinessReason: inner.readinessReason ?? null },
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** One published Action and whether it can run, as `?view=deployable` answers. */
|
|
62
|
+
export interface DeployableActionEntry {
|
|
63
|
+
definition: { apiName: string; displayName?: string; id?: string }
|
|
64
|
+
contractDigest?: string
|
|
65
|
+
availability?: string
|
|
66
|
+
executable?: boolean
|
|
67
|
+
deploymentStatus?: string
|
|
68
|
+
reason?: string
|
|
69
|
+
/**
|
|
70
|
+
* What the deployed Action runs with that its owner should fix, without
|
|
71
|
+
* stopping it: a value it offers that the semantic type it writes refuses
|
|
72
|
+
* (`ACTION_SEMANTIC_TYPE_CONFLICT`). A request with that value is refused when submitted.
|
|
73
|
+
*/
|
|
74
|
+
warnings?: Array<{ code: string; path?: string; message: string }>
|
|
75
|
+
}
|
|
76
|
+
|
|
42
77
|
export interface ActionDiscovery {
|
|
43
78
|
actionDefinitionId: string
|
|
44
79
|
apiName: string
|
|
@@ -111,11 +146,18 @@ export class GovernedActionApi {
|
|
|
111
146
|
|
|
112
147
|
if (!response.ok) {
|
|
113
148
|
const body = payload as { message?: string; code?: string; details?: unknown } | null
|
|
149
|
+
// An Action that is published but has no deployment: said as that, not as a conflict.
|
|
150
|
+
const undeployed = notDeployedError(body?.details, path)
|
|
151
|
+
if (undeployed) throw undeployed
|
|
114
152
|
const credential = credentialFailure(response.status, body?.message, { token: this.token, code: body?.code, details: body?.details })
|
|
115
153
|
if (credential) throw credential
|
|
116
|
-
|
|
154
|
+
// A refusal whose reason is only in its issues ("Mutation Plan is invalid.") says the reason in the message.
|
|
155
|
+
const issues = issueLines(body?.details)
|
|
156
|
+
const said = body?.message ?? `${response.status} from ${path}`
|
|
157
|
+
throw new CliError(issues.length ? `${said} ${issues.join('; ')}` : said, {
|
|
117
158
|
code: body?.code ?? 'FAILURE',
|
|
118
|
-
...(body?.details ? { hint: JSON.stringify(body.details) } : {}),
|
|
159
|
+
...(body?.details ? { hint: issues.length ? issues.join('\n') : JSON.stringify(body.details) } : {}),
|
|
160
|
+
...(body?.details ? { details: body.details } : {}),
|
|
119
161
|
// The status is what separates "refused" from "unknown": `action
|
|
120
162
|
// submit` offers a retry only for the second.
|
|
121
163
|
cause: { status: response.status, details: body?.details },
|
|
@@ -275,6 +317,27 @@ export class GovernedActionApi {
|
|
|
275
317
|
return this.call('/v1/blueprint/actions')
|
|
276
318
|
}
|
|
277
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Every published Action with its readiness, the inert ones included —
|
|
322
|
+
* `?view=deployable`. The plain list keeps only Actions that can be
|
|
323
|
+
* invoked, so one published and switched off was missing from it. Null
|
|
324
|
+
* when the service predates the view (it refuses the query).
|
|
325
|
+
*/
|
|
326
|
+
async listDeployableActions(): Promise<DeployableActionEntry[] | null> {
|
|
327
|
+
try {
|
|
328
|
+
return await this.call<DeployableActionEntry[]>('/v1/blueprint/actions?view=deployable')
|
|
329
|
+
} catch (err) {
|
|
330
|
+
const status = ((err as { cause?: { status?: number } }).cause)?.status
|
|
331
|
+
if (status === 400 || status === 422) return null
|
|
332
|
+
throw err
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** The Actions authored on the draft, published or not — `?view=draft`. */
|
|
337
|
+
listDraftActions(): Promise<Array<Record<string, unknown>>> {
|
|
338
|
+
return this.call('/v1/blueprint/actions?view=draft')
|
|
339
|
+
}
|
|
340
|
+
|
|
278
341
|
/**
|
|
279
342
|
* The ACTIVE view, never the draft: a deployment is checked against the
|
|
280
343
|
* release the write path will actually read, and a draft-only property would
|
|
@@ -433,3 +496,28 @@ export class GovernedActionApi {
|
|
|
433
496
|
return this.call(`/v1/blueprint/governed-actions/admin/bindings${query}`)
|
|
434
497
|
}
|
|
435
498
|
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* A validation refusal's issues (`details.issues: [{ kind?, path, message }]`,
|
|
502
|
+
* `kind` being `invocation_input` or `invocation` for a submission), one line
|
|
503
|
+
* each as `path: message`, and a stale version's `details.currentVersion` as
|
|
504
|
+
* the version to submit instead; empty when the details carry neither.
|
|
505
|
+
*/
|
|
506
|
+
export function issueLines(details: unknown): string[] {
|
|
507
|
+
const d = (details && typeof details === 'object' ? details : {}) as { issues?: unknown; currentVersion?: unknown }
|
|
508
|
+
const lines: string[] = []
|
|
509
|
+
if (Array.isArray(d.issues)) {
|
|
510
|
+
for (const i of d.issues) {
|
|
511
|
+
if (!i || typeof i !== 'object') continue
|
|
512
|
+
const { path, message } = i as { path?: unknown; message?: unknown }
|
|
513
|
+
if (typeof message !== 'string' || !message) continue
|
|
514
|
+
const steps = Array.isArray(path) ? path.map(String) : typeof path === 'string' && path ? [path] : []
|
|
515
|
+
const where = steps.join('.')
|
|
516
|
+
lines.push(where ? `${where}: ${message}` : message)
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
if (typeof d.currentVersion === 'number' || typeof d.currentVersion === 'string') {
|
|
520
|
+
lines.push(`the record is now at version ${String(d.currentVersion)}: read it again and submit with expectedVersion ${String(d.currentVersion)}`)
|
|
521
|
+
}
|
|
522
|
+
return [...new Set(lines)].slice(0, 8)
|
|
523
|
+
}
|
package/src/api/platform-api.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FronteraClient } from '@frontera-sdk/core/client'
|
|
2
2
|
|
|
3
|
+
import type { MetricQueryBody, MetricQueryResult } from '../blueprint/metric-query'
|
|
3
4
|
import { organizationHeaders, selectedOrganization } from '../organization'
|
|
4
5
|
|
|
5
6
|
import { CliError } from '../errors'
|
|
@@ -22,6 +23,22 @@ function statusCode(status: number): string {
|
|
|
22
23
|
return 'FAILURE'
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* How a knowledge search cut its results. The cutoff is a maximum cosine
|
|
28
|
+
* distance (0 to 2, lower is stricter) while `score` is higher-is-better:
|
|
29
|
+
* with similarity scoring a score is `1 - distance / 2`, so the cutoff lets
|
|
30
|
+
* through scores above `minScore`.
|
|
31
|
+
*/
|
|
32
|
+
export interface KnowledgeRetrieval {
|
|
33
|
+
maxDistance?: number
|
|
34
|
+
/** `base`: the base's own match threshold; `request`: `--threshold`. */
|
|
35
|
+
thresholdFrom?: 'base' | 'request'
|
|
36
|
+
scoring?: 'similarity' | 'fusion' | 'rerank'
|
|
37
|
+
minScore?: number | null
|
|
38
|
+
/** The nearest chunk's distance when none was kept; null when the base has nothing searchable. */
|
|
39
|
+
nearestDistance?: number | null
|
|
40
|
+
}
|
|
41
|
+
|
|
25
42
|
export interface AgentDraft {
|
|
26
43
|
agentId?: string
|
|
27
44
|
revision: number
|
|
@@ -120,12 +137,49 @@ export class PlatformApi {
|
|
|
120
137
|
return this.getList<unknown>('/v1/blueprint/metrics')
|
|
121
138
|
}
|
|
122
139
|
|
|
140
|
+
/** One published metric, with its definition (measures, dimensions, timeseries). */
|
|
141
|
+
blueprintMetric(apiName: string) {
|
|
142
|
+
return this.get<unknown>(`/v1/blueprint/metrics/${encodeURIComponent(apiName)}`)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** A metric's numbers, as an App's `useMetric` and an Agent's `blueprint_query_metric` read them (`blueprint/metric-query.ts`). */
|
|
146
|
+
blueprintMetricQuery(apiName: string, body: MetricQueryBody) {
|
|
147
|
+
return this.client.request<MetricQueryResult>(`/v1/blueprint/metrics/${encodeURIComponent(apiName)}/query`, { method: 'POST', body })
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* An aggregation over an object set (`POST /v1/blueprint/aggregate`). The
|
|
152
|
+
* metric command reads the newest value of a metric's timeseries with it: the
|
|
153
|
+
* point a `--range` window is counted back from.
|
|
154
|
+
*/
|
|
155
|
+
blueprintAggregate(body: unknown) {
|
|
156
|
+
return this.client.request<{ rows?: Array<Record<string, unknown>> }>('/v1/blueprint/aggregate', { method: 'POST', body })
|
|
157
|
+
}
|
|
158
|
+
|
|
123
159
|
/** How object types relate. Without these the catalog reads as a pile of
|
|
124
160
|
* disconnected tables, and nothing can be joined. */
|
|
125
161
|
blueprintLinkTypes() {
|
|
126
162
|
return this.getList<unknown>('/v1/blueprint/link-types')
|
|
127
163
|
}
|
|
128
164
|
|
|
165
|
+
/**
|
|
166
|
+
* The saved object sets this credential can read, as the route answered.
|
|
167
|
+
*
|
|
168
|
+
* A workspace key reads its workspace's slice (`/v1/sync/object-sets`, rows
|
|
169
|
+
* name their object type); an organization key is refused there without a
|
|
170
|
+
* workspace and reads the organization's (`/v1/blueprint/object-sets`).
|
|
171
|
+
* Rows are normalized by `normalizeObjectSets`.
|
|
172
|
+
*/
|
|
173
|
+
async blueprintObjectSets(): Promise<unknown> {
|
|
174
|
+
try {
|
|
175
|
+
return await this.get<unknown>('/v1/sync/object-sets')
|
|
176
|
+
} catch (err) {
|
|
177
|
+
const status = (err as { status?: number }).status
|
|
178
|
+
if (status !== 400 && status !== 401 && status !== 403 && status !== 404) throw err
|
|
179
|
+
return this.get<unknown>('/v1/blueprint/object-sets')
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
129
183
|
/**
|
|
130
184
|
* Run an object-set query and return rows.
|
|
131
185
|
*
|
|
@@ -148,6 +202,8 @@ export class PlatformApi {
|
|
|
148
202
|
pageToken?: string
|
|
149
203
|
/** Distance ordering from a location; checked by the service. */
|
|
150
204
|
nearest?: unknown
|
|
205
|
+
/** Each row of an editable type carries `_meta.recordVersion`, what an Action's `expectedSubjectVersion` names. */
|
|
206
|
+
recordVersions?: boolean
|
|
151
207
|
}) {
|
|
152
208
|
return this.client.request<{
|
|
153
209
|
rows?: Array<Record<string, unknown>>
|
|
@@ -175,6 +231,11 @@ export class PlatformApi {
|
|
|
175
231
|
return this.getList<unknown>('/v1/config/agents')
|
|
176
232
|
}
|
|
177
233
|
|
|
234
|
+
/** Every Agent in the workspace, drafts never published included (the sync listing; `agents()` lists published ones). */
|
|
235
|
+
allAgents() {
|
|
236
|
+
return this.getList<unknown>('/v1/sync/agents')
|
|
237
|
+
}
|
|
238
|
+
|
|
178
239
|
agent(id: string) {
|
|
179
240
|
return this.get<unknown>(`/v1/config/agents/${encodeURIComponent(id)}`)
|
|
180
241
|
}
|
|
@@ -304,6 +365,21 @@ export class PlatformApi {
|
|
|
304
365
|
})
|
|
305
366
|
}
|
|
306
367
|
|
|
368
|
+
/** Archive an Agent: out of service, its conversations kept; `restoreAgent` puts it back. The platform's delete is this archive. */
|
|
369
|
+
archiveAgent(id: string) {
|
|
370
|
+
return this.client.request<unknown>(`/v1/config/agents/${encodeURIComponent(id)}`, {
|
|
371
|
+
method: 'DELETE',
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Put an archived Agent back into service, as it was. */
|
|
376
|
+
restoreAgent(id: string) {
|
|
377
|
+
return this.client.request<unknown>(`/v1/config/agents/${encodeURIComponent(id)}/restore`, {
|
|
378
|
+
method: 'POST',
|
|
379
|
+
body: {},
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
|
|
307
383
|
agentVersions(id: string) {
|
|
308
384
|
return this.getList<unknown>(`/v1/config/agents/${encodeURIComponent(id)}/versions`)
|
|
309
385
|
}
|
|
@@ -657,7 +733,7 @@ export class PlatformApi {
|
|
|
657
733
|
async knowledgeSearch(
|
|
658
734
|
baseId: string,
|
|
659
735
|
body: { query: string; topK?: number; threshold?: number },
|
|
660
|
-
): Promise<{ results: Array<Record<string, unknown
|
|
736
|
+
): Promise<{ results: Array<Record<string, unknown>>; retrieval?: KnowledgeRetrieval }> {
|
|
661
737
|
const res = await this.client.request<unknown>(
|
|
662
738
|
`/v1/workspace-knowledge/${encodeURIComponent(baseId)}/search`,
|
|
663
739
|
{ method: 'POST', body },
|
|
@@ -669,7 +745,16 @@ export class PlatformApi {
|
|
|
669
745
|
// search; it went unnoticed because the first base tried was empty, which
|
|
670
746
|
// produces the identical output.
|
|
671
747
|
const rows = (payload.results ?? payload.chunks) as Array<Record<string, unknown>> | undefined
|
|
672
|
-
|
|
748
|
+
// How the cutoff applied and how to read `score` against it; absent from a service that predates it.
|
|
749
|
+
const retrieval = payload.retrieval && typeof payload.retrieval === 'object' ? (payload.retrieval as KnowledgeRetrieval) : undefined
|
|
750
|
+
return { results: Array.isArray(rows) ? rows : [], ...(retrieval ? { retrieval } : {}) }
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/** The organization's embedding model (`/v1/config/embedding`); both null when it has chosen none. */
|
|
754
|
+
async embeddingSetting(): Promise<{ provider: string | null; model: string | null }> {
|
|
755
|
+
const body = PlatformApi.inner<{ provider?: unknown; model?: unknown } | null>(await this.get<unknown>('/v1/config/embedding'))
|
|
756
|
+
const text = (v: unknown) => (typeof v === 'string' && v ? v : null)
|
|
757
|
+
return { provider: text(body?.provider), model: text(body?.model) }
|
|
673
758
|
}
|
|
674
759
|
|
|
675
760
|
/**
|