@stigmer/cli 3.5.2 → 3.6.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/commands/list.js +8 -5
- package/commands/list.js.map +1 -1
- package/commands/resume.js +5 -1
- package/commands/resume.js.map +1 -1
- package/commands/schedule.d.ts +3 -0
- package/commands/schedule.d.ts.map +1 -0
- package/commands/schedule.js +57 -0
- package/commands/schedule.js.map +1 -0
- package/package.json +5 -5
- package/program.d.ts.map +1 -1
- package/program.js +2 -0
- package/program.js.map +1 -1
- package/registry/metadata.d.ts.map +1 -1
- package/registry/metadata.js +2 -0
- package/registry/metadata.js.map +1 -1
- package/registry/verb-support.d.ts.map +1 -1
- package/registry/verb-support.js +29 -21
- package/registry/verb-support.js.map +1 -1
- package/registry/verbs.d.ts.map +1 -1
- package/registry/verbs.js +0 -1
- package/registry/verbs.js.map +1 -1
- package/resources/apply/apply.d.ts +6 -1
- package/resources/apply/apply.d.ts.map +1 -1
- package/resources/apply/apply.js +14 -24
- package/resources/apply/apply.js.map +1 -1
- package/resources/apply/handlers.d.ts +9 -1
- package/resources/apply/handlers.d.ts.map +1 -1
- package/resources/apply/handlers.js +50 -148
- package/resources/apply/handlers.js.map +1 -1
- package/resources/delete.d.ts +12 -0
- package/resources/delete.d.ts.map +1 -1
- package/resources/delete.js +8 -4
- package/resources/delete.js.map +1 -1
- package/resources/execution.d.ts +14 -4
- package/resources/execution.d.ts.map +1 -1
- package/resources/execution.js +16 -6
- package/resources/execution.js.map +1 -1
- package/resources/get-bindings.d.ts +1 -0
- package/resources/get-bindings.d.ts.map +1 -1
- package/resources/get-bindings.js +8 -1
- package/resources/get-bindings.js.map +1 -1
- package/resources/list.d.ts +4 -0
- package/resources/list.d.ts.map +1 -1
- package/resources/list.js +95 -27
- package/resources/list.js.map +1 -1
- package/resources/reference.d.ts +2 -0
- package/resources/reference.d.ts.map +1 -1
- package/resources/reference.js +4 -0
- package/resources/reference.js.map +1 -1
- package/resources/schedule.d.ts +19 -0
- package/resources/schedule.d.ts.map +1 -0
- package/resources/schedule.js +96 -0
- package/resources/schedule.js.map +1 -0
- package/src/commands/list.ts +8 -5
- package/src/commands/resume.ts +8 -1
- package/src/commands/schedule.ts +70 -0
- package/src/program.ts +2 -0
- package/src/registry/metadata.ts +2 -0
- package/src/registry/registry.test.ts +113 -8
- package/src/registry/verb-support.ts +29 -21
- package/src/registry/verbs.ts +0 -1
- package/src/resources/apply/apply.integration.test.ts +132 -0
- package/src/resources/apply/apply.ts +16 -25
- package/src/resources/apply/handlers.ts +60 -150
- package/src/resources/delete.ts +8 -4
- package/src/resources/execution.ts +20 -6
- package/src/resources/get-bindings.ts +8 -1
- package/src/resources/list.ts +107 -31
- package/src/resources/mutate-verbs.integration.test.ts +78 -4
- package/src/resources/read-verbs.integration.test.ts +124 -5
- package/src/resources/reference.ts +5 -0
- package/src/resources/schedule.ts +115 -0
|
@@ -1,178 +1,88 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Apply-handler registry for `apply -f` (file mode) and the synthesis track.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
3
|
+
// The declarative manifest kinds come from the SDK's manifest registry
|
|
4
|
+
// (`manifestKinds()` in @stigmer/sdk) — the one table binding a kind to its
|
|
5
|
+
// proto schema, its raw command-controller `apply` RPC, and its dependency
|
|
6
|
+
// apply order. The CLI consumes that table instead of keeping a copy: the
|
|
7
|
+
// copy this file used to carry drifted twice (ChannelApp was missing
|
|
8
|
+
// entirely — stigmer/stigmer#353 — and three kinds were absent from the
|
|
9
|
+
// local ordering map, so multi-document bundles applied on file-order luck).
|
|
10
10
|
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
11
|
+
// Both registries drive the *generated controllers* directly — not the
|
|
12
|
+
// high-level SDK `apply(input)` methods — because the SDK's `*Input`
|
|
13
|
+
// wrappers are lossy (they drop `metadata.id`, so an update would be
|
|
14
|
+
// misrouted as a create). The `apply` RPC takes the full resource message,
|
|
15
|
+
// preserving every field round-tripped from YAML.
|
|
16
|
+
//
|
|
17
|
+
// CLI_EXTRA_HANDLERS carries the kinds the CLI applies but the SDK's
|
|
18
|
+
// manifest engine deliberately does not treat as manifest kinds:
|
|
19
|
+
// Organization (not org-scoped — the bootstrap resource every other kind
|
|
20
|
+
// lives inside) and the runtime-instance kinds (WorkflowInstance, Session).
|
|
21
|
+
// A kind added here must also declare Apply in the registry's verb matrix —
|
|
22
|
+
// the conformance test in registry/registry.test.ts enforces both
|
|
23
|
+
// directions, so an entry without a matrix line (or vice versa) fails CI.
|
|
13
24
|
|
|
14
|
-
import type { Client } from "@connectrpc/connect";
|
|
15
25
|
import type { DescMessage, DescService, Message } from "@bufbuild/protobuf";
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
import { type Agent, AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
19
|
-
import { AgentCommandController } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/command_pb";
|
|
20
|
-
import { type AgentChannel, AgentChannelSchema } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/api_pb";
|
|
21
|
-
import { AgentChannelCommandController } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/command_pb";
|
|
22
|
-
import { type AgentInstance, AgentInstanceSchema } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/api_pb";
|
|
23
|
-
import { AgentInstanceCommandController } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/command_pb";
|
|
24
|
-
import { type AgentShare, AgentShareSchema } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/api_pb";
|
|
25
|
-
import { AgentShareCommandController } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/command_pb";
|
|
26
|
-
import { type Datastore, DatastoreSchema } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/api_pb";
|
|
27
|
-
import { DatastoreCommandController } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/command_pb";
|
|
28
|
-
import { type Environment, EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
29
|
-
import { EnvironmentCommandController } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/command_pb";
|
|
30
|
-
import { type McpServer, McpServerSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
31
|
-
import { McpServerCommandController } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/command_pb";
|
|
26
|
+
import type { Client } from "@connectrpc/connect";
|
|
32
27
|
import { type Session, SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
33
28
|
import { SessionCommandController } from "@stigmer/protos/ai/stigmer/agentic/session/v1/command_pb";
|
|
34
|
-
import { type Workflow, WorkflowSchema } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/api_pb";
|
|
35
|
-
import { WorkflowCommandController } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/command_pb";
|
|
36
29
|
import {
|
|
37
30
|
type WorkflowInstance,
|
|
38
31
|
WorkflowInstanceSchema,
|
|
39
32
|
} from "@stigmer/protos/ai/stigmer/agentic/workflowinstance/v1/api_pb";
|
|
40
33
|
import { WorkflowInstanceCommandController } from "@stigmer/protos/ai/stigmer/agentic/workflowinstance/v1/command_pb";
|
|
41
|
-
import {
|
|
42
|
-
import { IdentityProviderCommandController } from "@stigmer/protos/ai/stigmer/iam/identityprovider/v1/command_pb";
|
|
43
|
-
import { type OAuthApp, OAuthAppSchema } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/api_pb";
|
|
44
|
-
import { OAuthAppCommandController } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/command_pb";
|
|
34
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
45
35
|
import { type Organization, OrganizationSchema } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/api_pb";
|
|
46
36
|
import { OrganizationCommandController } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/command_pb";
|
|
37
|
+
import { manifestKinds } from "@stigmer/sdk";
|
|
47
38
|
|
|
48
39
|
/** Accessor for a raw Connect client over a generated service controller. */
|
|
49
40
|
export type ControllerFn = <Desc extends DescService>(service: Desc) => Client<Desc>;
|
|
50
41
|
|
|
51
42
|
export interface ApplyHandler {
|
|
52
43
|
readonly kind: ApiResourceKind;
|
|
44
|
+
/** Human-facing name for messages, e.g. "MCP Server". */
|
|
53
45
|
readonly displayName: string;
|
|
54
46
|
/** Proto schema for strict YAML→proto marshalling. */
|
|
55
47
|
readonly schema: DescMessage;
|
|
48
|
+
/**
|
|
49
|
+
* Position in the dependency apply order (ascending) — referenced kinds
|
|
50
|
+
* apply before their dependents. Manifest kinds carry the SDK registry's
|
|
51
|
+
* value; the CLI extras slot around them (organization first, the
|
|
52
|
+
* runtime-instance kinds after every blueprint they can reference).
|
|
53
|
+
*/
|
|
54
|
+
readonly applyOrder: number;
|
|
56
55
|
/** Drive the controller's `apply` RPC with the full resource message. */
|
|
57
56
|
apply(controller: ControllerFn, message: Message): Promise<Message>;
|
|
58
57
|
}
|
|
59
58
|
|
|
59
|
+
// The SDK registry's applyOrder values end at schedule = 12; the extras slot
|
|
60
|
+
// outside that range so a future SDK kind never collides with them.
|
|
61
|
+
const CLI_EXTRA_HANDLERS: readonly ApplyHandler[] = [
|
|
62
|
+
{
|
|
63
|
+
kind: ApiResourceKind.organization,
|
|
64
|
+
displayName: "Organization",
|
|
65
|
+
schema: OrganizationSchema,
|
|
66
|
+
applyOrder: 0,
|
|
67
|
+
apply: (c, m) => c(OrganizationCommandController).apply(m as Organization),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
kind: ApiResourceKind.workflow_instance,
|
|
71
|
+
displayName: "Workflow Instance",
|
|
72
|
+
schema: WorkflowInstanceSchema,
|
|
73
|
+
applyOrder: 13,
|
|
74
|
+
apply: (c, m) => c(WorkflowInstanceCommandController).apply(m as WorkflowInstance),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
kind: ApiResourceKind.session,
|
|
78
|
+
displayName: "Session",
|
|
79
|
+
schema: SessionSchema,
|
|
80
|
+
applyOrder: 14,
|
|
81
|
+
apply: (c, m) => c(SessionCommandController).apply(m as Session),
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
60
85
|
export const APPLY_HANDLERS: ReadonlyMap<ApiResourceKind, ApplyHandler> = new Map<ApiResourceKind, ApplyHandler>([
|
|
61
|
-
[
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
kind: ApiResourceKind.organization,
|
|
65
|
-
displayName: "Organization",
|
|
66
|
-
schema: OrganizationSchema,
|
|
67
|
-
apply: (c, m) => c(OrganizationCommandController).apply(m as Organization),
|
|
68
|
-
},
|
|
69
|
-
],
|
|
70
|
-
[
|
|
71
|
-
ApiResourceKind.mcp_server,
|
|
72
|
-
{
|
|
73
|
-
kind: ApiResourceKind.mcp_server,
|
|
74
|
-
displayName: "MCP Server",
|
|
75
|
-
schema: McpServerSchema,
|
|
76
|
-
apply: (c, m) => c(McpServerCommandController).apply(m as McpServer),
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
[
|
|
80
|
-
ApiResourceKind.datastore,
|
|
81
|
-
{
|
|
82
|
-
kind: ApiResourceKind.datastore,
|
|
83
|
-
displayName: "Datastore",
|
|
84
|
-
schema: DatastoreSchema,
|
|
85
|
-
apply: (c, m) => c(DatastoreCommandController).apply(m as Datastore),
|
|
86
|
-
},
|
|
87
|
-
],
|
|
88
|
-
[
|
|
89
|
-
ApiResourceKind.agent,
|
|
90
|
-
{
|
|
91
|
-
kind: ApiResourceKind.agent,
|
|
92
|
-
displayName: "Agent",
|
|
93
|
-
schema: AgentSchema,
|
|
94
|
-
apply: (c, m) => c(AgentCommandController).apply(m as Agent),
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
[
|
|
98
|
-
ApiResourceKind.workflow,
|
|
99
|
-
{
|
|
100
|
-
kind: ApiResourceKind.workflow,
|
|
101
|
-
displayName: "Workflow",
|
|
102
|
-
schema: WorkflowSchema,
|
|
103
|
-
apply: (c, m) => c(WorkflowCommandController).apply(m as Workflow),
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
[
|
|
107
|
-
ApiResourceKind.environment,
|
|
108
|
-
{
|
|
109
|
-
kind: ApiResourceKind.environment,
|
|
110
|
-
displayName: "Environment",
|
|
111
|
-
schema: EnvironmentSchema,
|
|
112
|
-
apply: (c, m) => c(EnvironmentCommandController).apply(m as Environment),
|
|
113
|
-
},
|
|
114
|
-
],
|
|
115
|
-
[
|
|
116
|
-
ApiResourceKind.identity_provider,
|
|
117
|
-
{
|
|
118
|
-
kind: ApiResourceKind.identity_provider,
|
|
119
|
-
displayName: "Identity Provider",
|
|
120
|
-
schema: IdentityProviderSchema,
|
|
121
|
-
apply: (c, m) => c(IdentityProviderCommandController).apply(m as IdentityProvider),
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
[
|
|
125
|
-
ApiResourceKind.oauth_app,
|
|
126
|
-
{
|
|
127
|
-
kind: ApiResourceKind.oauth_app,
|
|
128
|
-
displayName: "OAuth App",
|
|
129
|
-
schema: OAuthAppSchema,
|
|
130
|
-
apply: (c, m) => c(OAuthAppCommandController).apply(m as OAuthApp),
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
|
-
[
|
|
134
|
-
ApiResourceKind.agent_share,
|
|
135
|
-
{
|
|
136
|
-
kind: ApiResourceKind.agent_share,
|
|
137
|
-
displayName: "Agent Share",
|
|
138
|
-
schema: AgentShareSchema,
|
|
139
|
-
apply: (c, m) => c(AgentShareCommandController).apply(m as AgentShare),
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
[
|
|
143
|
-
ApiResourceKind.agent_channel,
|
|
144
|
-
{
|
|
145
|
-
kind: ApiResourceKind.agent_channel,
|
|
146
|
-
displayName: "Agent Channel",
|
|
147
|
-
schema: AgentChannelSchema,
|
|
148
|
-
apply: (c, m) => c(AgentChannelCommandController).apply(m as AgentChannel),
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
[
|
|
152
|
-
ApiResourceKind.agent_instance,
|
|
153
|
-
{
|
|
154
|
-
kind: ApiResourceKind.agent_instance,
|
|
155
|
-
displayName: "Agent Instance",
|
|
156
|
-
schema: AgentInstanceSchema,
|
|
157
|
-
apply: (c, m) => c(AgentInstanceCommandController).apply(m as AgentInstance),
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
[
|
|
161
|
-
ApiResourceKind.workflow_instance,
|
|
162
|
-
{
|
|
163
|
-
kind: ApiResourceKind.workflow_instance,
|
|
164
|
-
displayName: "Workflow Instance",
|
|
165
|
-
schema: WorkflowInstanceSchema,
|
|
166
|
-
apply: (c, m) => c(WorkflowInstanceCommandController).apply(m as WorkflowInstance),
|
|
167
|
-
},
|
|
168
|
-
],
|
|
169
|
-
[
|
|
170
|
-
ApiResourceKind.session,
|
|
171
|
-
{
|
|
172
|
-
kind: ApiResourceKind.session,
|
|
173
|
-
displayName: "Session",
|
|
174
|
-
schema: SessionSchema,
|
|
175
|
-
apply: (c, m) => c(SessionCommandController).apply(m as Session),
|
|
176
|
-
},
|
|
177
|
-
],
|
|
86
|
+
...manifestKinds().map((handler) => [handler.kind, handler] as const),
|
|
87
|
+
...CLI_EXTRA_HANDLERS.map((handler) => [handler.kind, handler] as const),
|
|
178
88
|
]);
|
package/src/resources/delete.ts
CHANGED
|
@@ -52,22 +52,26 @@ interface HasMetadata {
|
|
|
52
52
|
type DeleteFn = (client: Stigmer, id: string, force: boolean) => Promise<HasMetadata>;
|
|
53
53
|
|
|
54
54
|
// Kinds the unified delete handles directly, each bound to its SDK delete call.
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
55
|
+
// Every kind declaring Delete in the verb matrix must have an entry here (or a
|
|
56
|
+
// documented special case) — the conformance test in registry/registry.test.ts
|
|
57
|
+
// enforces it, so the two cannot drift.
|
|
58
58
|
// Kinds whose delete takes a DeleteResourceInput (not an ID) thread the force
|
|
59
59
|
// acknowledgment through; today only the datastore server honors it (the
|
|
60
60
|
// non-empty guard), but force is the contract's generic ack carrier.
|
|
61
|
-
const DELETE_HANDLERS: ReadonlyMap<ApiResourceKind, DeleteFn> = new Map<ApiResourceKind, DeleteFn>([
|
|
61
|
+
export const DELETE_HANDLERS: ReadonlyMap<ApiResourceKind, DeleteFn> = new Map<ApiResourceKind, DeleteFn>([
|
|
62
62
|
[ApiResourceKind.agent, (c, id) => c.agent.delete(id)],
|
|
63
63
|
[ApiResourceKind.agent_instance, (c, id) => c.agentInstance.delete(id)],
|
|
64
64
|
[ApiResourceKind.workflow, (c, id) => c.workflow.delete(id)],
|
|
65
|
+
[ApiResourceKind.workflow_instance, (c, id) => c.workflowInstance.delete(id)],
|
|
65
66
|
[ApiResourceKind.mcp_server, (c, id, force) => c.mcpServer.delete({ resourceId: id, force })],
|
|
66
67
|
[ApiResourceKind.project, (c, id) => c.project.delete(id)],
|
|
67
68
|
[ApiResourceKind.datastore, (c, id, force) => c.datastore.delete({ resourceId: id, force })],
|
|
68
69
|
[ApiResourceKind.environment, (c, id, force) => c.environment.delete({ resourceId: id, force })],
|
|
69
70
|
[ApiResourceKind.agent_channel, (c, id) => c.agentChannel.delete(id)],
|
|
70
71
|
[ApiResourceKind.channel_app, (c, id, force) => c.channelapp.delete({ resourceId: id, force })],
|
|
72
|
+
// A schedule delete also tears down its Temporal Schedule artifact
|
|
73
|
+
// server-side; the RPC takes a bare ScheduleId, so force is ignored.
|
|
74
|
+
[ApiResourceKind.schedule, (c, id) => c.schedule.delete(id)],
|
|
71
75
|
[ApiResourceKind.skill, (c, id) => c.skill.delete(id)],
|
|
72
76
|
[ApiResourceKind.api_key, (c, id) => c.apiKey.delete(id)],
|
|
73
77
|
]);
|
|
@@ -124,15 +124,29 @@ export async function getExecution(client: Stigmer, id: string): Promise<Resourc
|
|
|
124
124
|
return { schema: WorkflowExecutionSchema, message: await client.workflowExecution.get(id) };
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
/**
|
|
128
|
+
* List agent executions for the current context, paginated by `limit`.
|
|
129
|
+
*
|
|
130
|
+
* `org` scopes results to that organization; empty means permission-bounded
|
|
131
|
+
* (all orgs the caller can view — the OSS single-tenant behavior).
|
|
132
|
+
*/
|
|
133
|
+
export async function listAgentExecutions(client: Stigmer, limit: number, org = ""): Promise<ResourceResult> {
|
|
134
|
+
const message = await client.agentExecution.list(
|
|
135
|
+
create(ListAgentExecutionsRequestSchema, { pageSize: limit, org }),
|
|
136
|
+
);
|
|
130
137
|
return { schema: AgentExecutionListSchema, message };
|
|
131
138
|
}
|
|
132
139
|
|
|
133
|
-
/**
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
/**
|
|
141
|
+
* List workflow executions for the current context, paginated by `limit`.
|
|
142
|
+
*
|
|
143
|
+
* `org` scopes results to that organization; empty means permission-bounded
|
|
144
|
+
* (all orgs the caller can view — the OSS single-tenant behavior).
|
|
145
|
+
*/
|
|
146
|
+
export async function listWorkflowExecutions(client: Stigmer, limit: number, org = ""): Promise<ResourceResult> {
|
|
147
|
+
const message = await client.workflowExecution.list(
|
|
148
|
+
create(ListWorkflowExecutionsRequestSchema, { pageSize: limit, org }),
|
|
149
|
+
);
|
|
136
150
|
return { schema: WorkflowExecutionListSchema, message };
|
|
137
151
|
}
|
|
138
152
|
|
|
@@ -11,8 +11,10 @@ import { ChannelAppSchema } from "@stigmer/protos/ai/stigmer/agentic/channelapp/
|
|
|
11
11
|
import { DatastoreSchema } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/api_pb";
|
|
12
12
|
import { EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
13
13
|
import { McpServerSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
14
|
+
import { ScheduleSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
|
|
14
15
|
import { SkillSchema } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
|
|
15
16
|
import { WorkflowSchema } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/api_pb";
|
|
17
|
+
import { WorkflowInstanceSchema } from "@stigmer/protos/ai/stigmer/agentic/workflowinstance/v1/api_pb";
|
|
16
18
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
17
19
|
import { ApiKeySchema } from "@stigmer/protos/ai/stigmer/iam/apikey/v1/api_pb";
|
|
18
20
|
import { ProjectSchema } from "@stigmer/protos/ai/stigmer/tenancy/project/v1/api_pb";
|
|
@@ -27,16 +29,21 @@ export interface ResourceResult {
|
|
|
27
29
|
|
|
28
30
|
type Getter = (client: Stigmer, ref: ParsedReference) => Promise<ResourceResult>;
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
// Every kind declaring Get in the verb matrix must have an entry here (or a
|
|
33
|
+
// documented special case, e.g. organization) — the conformance test in
|
|
34
|
+
// registry/registry.test.ts enforces it, so the two cannot drift.
|
|
35
|
+
export const GET_BINDINGS: ReadonlyMap<ApiResourceKind, Getter> = new Map([
|
|
31
36
|
[ApiResourceKind.agent, refGetter(ApiResourceKind.agent, AgentSchema, (c) => c.agent)],
|
|
32
37
|
[ApiResourceKind.agent_instance, refGetter(ApiResourceKind.agent_instance, AgentInstanceSchema, (c) => c.agentInstance)],
|
|
33
38
|
[ApiResourceKind.workflow, refGetter(ApiResourceKind.workflow, WorkflowSchema, (c) => c.workflow)],
|
|
39
|
+
[ApiResourceKind.workflow_instance, refGetter(ApiResourceKind.workflow_instance, WorkflowInstanceSchema, (c) => c.workflowInstance)],
|
|
34
40
|
[ApiResourceKind.mcp_server, refGetter(ApiResourceKind.mcp_server, McpServerSchema, (c) => c.mcpServer)],
|
|
35
41
|
[ApiResourceKind.project, refGetter(ApiResourceKind.project, ProjectSchema, (c) => c.project)],
|
|
36
42
|
[ApiResourceKind.datastore, refGetter(ApiResourceKind.datastore, DatastoreSchema, (c) => c.datastore)],
|
|
37
43
|
[ApiResourceKind.environment, refGetter(ApiResourceKind.environment, EnvironmentSchema, (c) => c.environment)],
|
|
38
44
|
[ApiResourceKind.agent_channel, refGetter(ApiResourceKind.agent_channel, AgentChannelSchema, (c) => c.agentChannel)],
|
|
39
45
|
[ApiResourceKind.channel_app, refGetter(ApiResourceKind.channel_app, ChannelAppSchema, (c) => c.channelapp)],
|
|
46
|
+
[ApiResourceKind.schedule, refGetter(ApiResourceKind.schedule, ScheduleSchema, (c) => c.schedule)],
|
|
40
47
|
[ApiResourceKind.skill, refGetter(ApiResourceKind.skill, SkillSchema, (c) => c.skill)],
|
|
41
48
|
[ApiResourceKind.api_key, idOnlyGetter(ApiKeySchema, (c) => c.apiKey, "API keys")],
|
|
42
49
|
]);
|
package/src/resources/list.ts
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Most registry kinds are search-indexed and list through the unified
|
|
4
4
|
// SearchService. Kinds that are deliberately not search-indexed
|
|
5
|
-
// (organizations, API keys, agent instances, agent channels, channel apps
|
|
6
|
-
// use their dedicated find/list RPCs with bespoke table shapes
|
|
5
|
+
// (organizations, API keys, agent instances, agent channels, channel apps,
|
|
6
|
+
// schedules) use their dedicated find/list RPCs with bespoke table shapes,
|
|
7
|
+
// registered in LIST_HANDLERS — the same map-dispatch shape as the get,
|
|
8
|
+
// delete, and apply registries, so the conformance test in
|
|
9
|
+
// registry/registry.test.ts can hold all four to the verb matrix.
|
|
7
10
|
|
|
8
11
|
import { create } from "@bufbuild/protobuf";
|
|
9
12
|
import { AgentChannelSchema } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/api_pb";
|
|
@@ -12,6 +15,8 @@ import { AgentInstanceSchema } from "@stigmer/protos/ai/stigmer/agentic/agentins
|
|
|
12
15
|
import { ListAgentInstancesRequestSchema } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/io_pb";
|
|
13
16
|
import { ChannelAppSchema } from "@stigmer/protos/ai/stigmer/agentic/channelapp/v1/api_pb";
|
|
14
17
|
import { ListChannelAppsByOrgInputSchema } from "@stigmer/protos/ai/stigmer/agentic/channelapp/v1/io_pb";
|
|
18
|
+
import { ScheduleSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
|
|
19
|
+
import { ListSchedulesRequestSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/io_pb";
|
|
15
20
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
16
21
|
import { PageInfoSchema } from "@stigmer/protos/ai/stigmer/commons/rpc/pagination_pb";
|
|
17
22
|
import { ApiKeySchema } from "@stigmer/protos/ai/stigmer/iam/apikey/v1/api_pb";
|
|
@@ -26,9 +31,9 @@ import { bool, type JsonObject, obj, renderCollection, str, type TableShape } fr
|
|
|
26
31
|
// scope). Must stay in step with the server's SearchableKinds allowlist
|
|
27
32
|
// (backend/services/stigmer-server/pkg/query/search/valueobject/
|
|
28
33
|
// search_criteria.go): a kind present here but absent there silently lists
|
|
29
|
-
// as empty.
|
|
30
|
-
//
|
|
31
|
-
const SEARCH_KINDS = new Set<ApiResourceKind>([
|
|
34
|
+
// as empty. The LIST_HANDLERS kinds are deliberately NOT here — they are
|
|
35
|
+
// not_search_indexed by design and take dedicated-RPC handlers below.
|
|
36
|
+
export const SEARCH_KINDS: ReadonlySet<ApiResourceKind> = new Set<ApiResourceKind>([
|
|
32
37
|
ApiResourceKind.agent,
|
|
33
38
|
ApiResourceKind.workflow,
|
|
34
39
|
ApiResourceKind.mcp_server,
|
|
@@ -38,6 +43,73 @@ const SEARCH_KINDS = new Set<ApiResourceKind>([
|
|
|
38
43
|
ApiResourceKind.environment,
|
|
39
44
|
]);
|
|
40
45
|
|
|
46
|
+
type ListFn = (client: Stigmer, org: string, limit: number, format: OutputFormat) => Promise<string>;
|
|
47
|
+
|
|
48
|
+
// Dedicated-RPC list handlers for the non-search-indexed kinds. Every kind
|
|
49
|
+
// declaring List in the verb matrix must appear here or in SEARCH_KINDS —
|
|
50
|
+
// the conformance test enforces it, so the two cannot drift.
|
|
51
|
+
export const LIST_HANDLERS: ReadonlyMap<ApiResourceKind, ListFn> = new Map<ApiResourceKind, ListFn>([
|
|
52
|
+
[
|
|
53
|
+
ApiResourceKind.organization,
|
|
54
|
+
async (client, _org, _limit, format) => {
|
|
55
|
+
const result = await client.organization.findMyOrganizations();
|
|
56
|
+
return renderCollection(OrganizationSchema, result.entries, format, ORG_TABLE);
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
ApiResourceKind.api_key,
|
|
61
|
+
async (client, _org, _limit, format) => {
|
|
62
|
+
const result = await client.apiKey.findAll();
|
|
63
|
+
return renderCollection(ApiKeySchema, result.entries, format, APIKEY_TABLE);
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
ApiResourceKind.agent_instance,
|
|
68
|
+
async (client, org, limit, format) => {
|
|
69
|
+
const result = await client.agentInstance.list(
|
|
70
|
+
create(ListAgentInstancesRequestSchema, { org, pageInfo: create(PageInfoSchema, { num: 1, size: limit }) }),
|
|
71
|
+
);
|
|
72
|
+
return renderCollection(AgentInstanceSchema, result.items, format, INSTANCE_TABLE);
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
[
|
|
76
|
+
ApiResourceKind.agent_channel,
|
|
77
|
+
async (client, org, limit, format) => {
|
|
78
|
+
const result = await client.agentChannel.list(
|
|
79
|
+
create(ListAgentChannelsRequestSchema, { org, pageInfo: create(PageInfoSchema, { num: 1, size: limit }) }),
|
|
80
|
+
);
|
|
81
|
+
return renderCollection(AgentChannelSchema, result.items, format, AGENT_CHANNEL_TABLE);
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
[
|
|
85
|
+
ApiResourceKind.channel_app,
|
|
86
|
+
async (client, org, limit, format) => {
|
|
87
|
+
// listByOrg has no pagination on its contract (the per-org set is small
|
|
88
|
+
// by design); the limit is applied client-side so --limit stays honest.
|
|
89
|
+
// `channelapp` (not `channelApp`) is a recorded SDK codegen naming quirk.
|
|
90
|
+
const result = await client.channelapp.listByOrg(create(ListChannelAppsByOrgInputSchema, { org }));
|
|
91
|
+
return renderCollection(ChannelAppSchema, result.entries.slice(0, limit), format, CHANNEL_APP_TABLE);
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
ApiResourceKind.schedule,
|
|
96
|
+
async (client, org, limit, format) => {
|
|
97
|
+
// ListSchedulesRequest requires an org (min_len 1), but an unset cloud
|
|
98
|
+
// context resolves to "" — refuse with actionable copy instead of
|
|
99
|
+
// relaying the server's raw validation error.
|
|
100
|
+
if (org === "") {
|
|
101
|
+
throw new UsageError(
|
|
102
|
+
"schedules are org-scoped: pass --org <slug> or configure an organization context",
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const result = await client.schedule.list(
|
|
106
|
+
create(ListSchedulesRequestSchema, { org, pageInfo: create(PageInfoSchema, { num: 1, size: limit }) }),
|
|
107
|
+
);
|
|
108
|
+
return renderCollection(ScheduleSchema, result.items, format, SCHEDULE_TABLE);
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
]);
|
|
112
|
+
|
|
41
113
|
export async function listResources(
|
|
42
114
|
client: Stigmer,
|
|
43
115
|
kind: ApiResourceKind,
|
|
@@ -45,32 +117,9 @@ export async function listResources(
|
|
|
45
117
|
limit: number,
|
|
46
118
|
format: OutputFormat,
|
|
47
119
|
): Promise<string> {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return
|
|
51
|
-
}
|
|
52
|
-
if (kind === ApiResourceKind.api_key) {
|
|
53
|
-
const result = await client.apiKey.findAll();
|
|
54
|
-
return renderCollection(ApiKeySchema, result.entries, format, APIKEY_TABLE);
|
|
55
|
-
}
|
|
56
|
-
if (kind === ApiResourceKind.agent_instance) {
|
|
57
|
-
const result = await client.agentInstance.list(
|
|
58
|
-
create(ListAgentInstancesRequestSchema, { org, pageInfo: create(PageInfoSchema, { num: 1, size: limit }) }),
|
|
59
|
-
);
|
|
60
|
-
return renderCollection(AgentInstanceSchema, result.items, format, INSTANCE_TABLE);
|
|
61
|
-
}
|
|
62
|
-
if (kind === ApiResourceKind.agent_channel) {
|
|
63
|
-
const result = await client.agentChannel.list(
|
|
64
|
-
create(ListAgentChannelsRequestSchema, { org, pageInfo: create(PageInfoSchema, { num: 1, size: limit }) }),
|
|
65
|
-
);
|
|
66
|
-
return renderCollection(AgentChannelSchema, result.items, format, AGENT_CHANNEL_TABLE);
|
|
67
|
-
}
|
|
68
|
-
if (kind === ApiResourceKind.channel_app) {
|
|
69
|
-
// listByOrg has no pagination on its contract (the per-org set is small
|
|
70
|
-
// by design); the limit is applied client-side so --limit stays honest.
|
|
71
|
-
// `channelapp` (not `channelApp`) is a recorded SDK codegen naming quirk.
|
|
72
|
-
const result = await client.channelapp.listByOrg(create(ListChannelAppsByOrgInputSchema, { org }));
|
|
73
|
-
return renderCollection(ChannelAppSchema, result.entries.slice(0, limit), format, CHANNEL_APP_TABLE);
|
|
120
|
+
const dedicated = LIST_HANDLERS.get(kind);
|
|
121
|
+
if (dedicated !== undefined) {
|
|
122
|
+
return dedicated(client, org, limit, format);
|
|
74
123
|
}
|
|
75
124
|
if (!SEARCH_KINDS.has(kind)) {
|
|
76
125
|
throw new UsageError("list is not implemented for this resource type");
|
|
@@ -146,6 +195,33 @@ const CHANNEL_APP_TABLE: TableShape = {
|
|
|
146
195
|
},
|
|
147
196
|
};
|
|
148
197
|
|
|
198
|
+
// ENABLED is the owner's switch (spec.enabled); STATE is the platform's
|
|
199
|
+
// failure latch, derived from status.paused_reason. They are different
|
|
200
|
+
// states with different remedies — re-apply with `enabled: true` versus
|
|
201
|
+
// `stigmer schedule resume` — so the table keeps them as two columns. An
|
|
202
|
+
// auto-paused schedule with ENABLED true is exactly the condition this
|
|
203
|
+
// surface exists to make visible (stigmer/stigmer#352).
|
|
204
|
+
const SCHEDULE_TABLE: TableShape = {
|
|
205
|
+
resourceName: "schedules",
|
|
206
|
+
headers: ["ID", "SLUG", "TARGET", "CRON", "TZ", "ENABLED", "STATE"],
|
|
207
|
+
row: (json) => {
|
|
208
|
+
const metadata = obj(json, "metadata");
|
|
209
|
+
const spec = obj(json, "spec");
|
|
210
|
+
// The target oneof has one arm today (`agent`); a future workflow arm
|
|
211
|
+
// extends this accessor alongside the proto.
|
|
212
|
+
const agentRef = obj(obj(spec, "agent"), "agent_ref");
|
|
213
|
+
return [
|
|
214
|
+
str(metadata, "id"),
|
|
215
|
+
str(metadata, "slug"),
|
|
216
|
+
`${str(agentRef, "org")}/${str(agentRef, "slug")}`,
|
|
217
|
+
str(spec, "cron"),
|
|
218
|
+
str(spec, "time_zone"),
|
|
219
|
+
bool(spec, "enabled") ? "true" : "false",
|
|
220
|
+
str(obj(json, "status"), "paused_reason") === "" ? "active" : "paused",
|
|
221
|
+
];
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
|
|
149
225
|
// The provider_config oneof serializes as exactly one provider-named key in
|
|
150
226
|
// protojson (AgentChannelSpec and ChannelAppSpec share the same oneof
|
|
151
227
|
// shape). Extend this list when a new provider arm lands in the protos.
|