@agent-compose/sdk 0.3.0 → 0.4.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/dist/client.d.ts CHANGED
@@ -132,6 +132,27 @@ export interface UpdateFactoryInput {
132
132
  name?: string;
133
133
  description?: string;
134
134
  }
135
+ export interface ScheduleRow {
136
+ id: string;
137
+ name: string;
138
+ workflowName: string;
139
+ cron: string;
140
+ createdAt: string;
141
+ updatedAt: string;
142
+ nextFireAt: string | null;
143
+ lastFireAt: string | null;
144
+ }
145
+ export interface CreateScheduleInput {
146
+ /** Human-friendly schedule name. Unique within the factory. */
147
+ name: string;
148
+ /** The workflow this schedule should fire. Must already be registered
149
+ * in the same factory. */
150
+ workflow: string;
151
+ /** Cron expression (UTC). */
152
+ cron: string;
153
+ /** Factory to attach the schedule to. Defaults to `"default"`. */
154
+ factorySlug?: string;
155
+ }
135
156
  export interface SecretOptions {
136
157
  factorySlug?: string;
137
158
  }
@@ -424,6 +445,21 @@ export declare class AgentComposeClient {
424
445
  /** Delete a factory. Refuses `default` and any factory still
425
446
  * containing workflows. */
426
447
  deleteFactory(slug: string): Promise<void>;
448
+ /** List every schedule in a factory, with the engine-reported next/last
449
+ * fire times merged in. */
450
+ listSchedules(factorySlug?: string): Promise<ScheduleRow[]>;
451
+ /** Create a new schedule. `name` is per-factory unique; the server
452
+ * returns 409 on collision. */
453
+ createSchedule(payload: CreateScheduleInput): Promise<{
454
+ id: string;
455
+ name: string;
456
+ workflow: string;
457
+ cron: string;
458
+ }>;
459
+ /** Delete a schedule by id. Best-effort: a transient engine error is
460
+ * logged server-side but the DB row is removed regardless — the boot
461
+ * reconciler reconverges on next start. */
462
+ deleteSchedule(id: string, factorySlug?: string): Promise<void>;
427
463
  /** Create or update a workflow secret. Value is stored in GCP Secret Manager. */
428
464
  setSecret(workflowName: string, key: string, value: string, opts?: SecretOptions): Promise<SetSecretResult>;
429
465
  /** List secret keys registered for a workflow (metadata only — values are never returned). */
package/dist/index.js CHANGED
@@ -477,6 +477,8 @@ var WORKFLOW_BRAND = Symbol.for("@agent-compose/sdk.Workflow");
477
477
  // src/types/workflow-metadata.ts
478
478
  function extractMetadata(source) {
479
479
  const out = {};
480
+ if (source.description !== undefined)
481
+ out.description = source.description;
480
482
  if (source.networkPolicy !== undefined)
481
483
  out.networkPolicy = freezeMetadataValue(source.networkPolicy);
482
484
  if (source.placeholders !== undefined)
@@ -587,6 +589,7 @@ function defineSandboxEnvironment(env) {
587
589
  throw new Error(`defineSandboxEnvironment(${env.name}): 'setup' must be a function`);
588
590
  }
589
591
  return defineWorkflow({
592
+ ...env.description !== undefined ? { description: env.description } : {},
590
593
  snapshots: env.snapshots ?? { saveLatest: true },
591
594
  memory: env.memory ?? false,
592
595
  run: async (_ctx, sandbox) => env.setup(sandbox)
@@ -858,6 +861,20 @@ class AgentComposeClient {
858
861
  deleteFactory(slug) {
859
862
  return this.fetch(`/api/v1/factories/${encodeURIComponent(slug)}`, { method: "DELETE" });
860
863
  }
864
+ async listSchedules(factorySlug = "default") {
865
+ const body = await this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules`);
866
+ return body.schedules;
867
+ }
868
+ createSchedule(payload) {
869
+ const factorySlug = payload.factorySlug ?? "default";
870
+ return this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules`, {
871
+ method: "POST",
872
+ body: { name: payload.name, workflow: payload.workflow, cron: payload.cron }
873
+ });
874
+ }
875
+ deleteSchedule(id, factorySlug = "default") {
876
+ return this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules/${encodeURIComponent(id)}`, { method: "DELETE" });
877
+ }
861
878
  setSecret(workflowName, key, value, opts) {
862
879
  const factorySlug = opts?.factorySlug ?? DEFAULT_FACTORY;
863
880
  return this.fetch(templatePath(factorySlug, workflowName, "secrets"), {
@@ -477,6 +477,8 @@ var WORKFLOW_BRAND = Symbol.for("@agent-compose/sdk.Workflow");
477
477
  // src/types/workflow-metadata.ts
478
478
  function extractMetadata(source) {
479
479
  const out = {};
480
+ if (source.description !== undefined)
481
+ out.description = source.description;
480
482
  if (source.networkPolicy !== undefined)
481
483
  out.networkPolicy = freezeMetadataValue(source.networkPolicy);
482
484
  if (source.placeholders !== undefined)
@@ -587,6 +589,7 @@ function defineSandboxEnvironment(env) {
587
589
  throw new Error(`defineSandboxEnvironment(${env.name}): 'setup' must be a function`);
588
590
  }
589
591
  return defineWorkflow({
592
+ ...env.description !== undefined ? { description: env.description } : {},
590
593
  snapshots: env.snapshots ?? { saveLatest: true },
591
594
  memory: env.memory ?? false,
592
595
  run: async (_ctx, sandbox) => env.setup(sandbox)
@@ -858,6 +861,20 @@ class AgentComposeClient {
858
861
  deleteFactory(slug) {
859
862
  return this.fetch(`/api/v1/factories/${encodeURIComponent(slug)}`, { method: "DELETE" });
860
863
  }
864
+ async listSchedules(factorySlug = "default") {
865
+ const body = await this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules`);
866
+ return body.schedules;
867
+ }
868
+ createSchedule(payload) {
869
+ const factorySlug = payload.factorySlug ?? "default";
870
+ return this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules`, {
871
+ method: "POST",
872
+ body: { name: payload.name, workflow: payload.workflow, cron: payload.cron }
873
+ });
874
+ }
875
+ deleteSchedule(id, factorySlug = "default") {
876
+ return this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules/${encodeURIComponent(id)}`, { method: "DELETE" });
877
+ }
861
878
  setSecret(workflowName, key, value, opts) {
862
879
  const factorySlug = opts?.factorySlug ?? DEFAULT_FACTORY;
863
880
  return this.fetch(templatePath(factorySlug, workflowName, "secrets"), {
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Regression test: `defineSandboxEnvironment.description` must reach
3
+ * the workflow's metadata so the dashboard template tile shows it
4
+ * instead of "No description.".
5
+ *
6
+ * Earlier the wrapper dropped the field on the floor — `agent-env`
7
+ * literally had `description: "..."` in source but the dashboard
8
+ * rendered "No description." because nothing propagated it through to
9
+ * `WorkflowMetadata.description`.
10
+ */
11
+ export {};
@@ -72,6 +72,11 @@ export interface IOSchema {
72
72
  * output-only release. New code should prefer `IOSchema`. */
73
73
  export type OutputSchema = IOSchema;
74
74
  export interface WorkflowMetadata {
75
+ /** One-line, human-readable description of what the workflow does.
76
+ * Surfaced on the dashboard template tile + run page header. Authors
77
+ * set it via `defineWorkflow({ description: "..." })` (either shape)
78
+ * or `defineSandboxEnvironment({ description: "..." })`. */
79
+ description?: string;
75
80
  networkPolicy?: SandboxNetworkPolicy;
76
81
  placeholders?: Record<string, string>;
77
82
  /** Input schema captured at bundle time from the workflow's
@@ -67,6 +67,9 @@ export type WorkflowFn<TOutput = unknown, TInput extends Record<string, unknown>
67
67
  * works — the workflow just runs with secrets passed directly in env.
68
68
  */
69
69
  export interface WorkflowDefinition<TOutput = unknown, TInput extends Record<string, unknown> = Record<string, unknown>> {
70
+ /** One-line, human-readable description of what this workflow does.
71
+ * Surfaced on the dashboard template tile + run page header. */
72
+ description?: string;
70
73
  run: WorkflowFn<TOutput, TInput>;
71
74
  /**
72
75
  * All snapshot config — boot source plus capture mode.
@@ -38,6 +38,9 @@ export interface WorkflowBuilder<TInput, TCurrent> {
38
38
  }
39
39
  export interface StepWorkflowDefinition<TInput, TOutput> {
40
40
  id: string;
41
+ /** One-line, human-readable description of what this workflow does.
42
+ * Surfaced on the dashboard template tile + run page header. */
43
+ description?: string;
41
44
  input: z.ZodType<TInput>;
42
45
  output: z.ZodType<TOutput>;
43
46
  networkPolicy?: SandboxNetworkPolicy;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-compose/sdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Client library for agent-compose — define agents, runtimes, and workflows, and invoke them against an agent-compose server.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/client.ts CHANGED
@@ -177,6 +177,29 @@ export interface UpdateFactoryInput {
177
177
  description?: string;
178
178
  }
179
179
 
180
+ export interface ScheduleRow {
181
+ id: string;
182
+ name: string;
183
+ workflowName: string;
184
+ cron: string;
185
+ createdAt: string;
186
+ updatedAt: string;
187
+ nextFireAt: string | null;
188
+ lastFireAt: string | null;
189
+ }
190
+
191
+ export interface CreateScheduleInput {
192
+ /** Human-friendly schedule name. Unique within the factory. */
193
+ name: string;
194
+ /** The workflow this schedule should fire. Must already be registered
195
+ * in the same factory. */
196
+ workflow: string;
197
+ /** Cron expression (UTC). */
198
+ cron: string;
199
+ /** Factory to attach the schedule to. Defaults to `"default"`. */
200
+ factorySlug?: string;
201
+ }
202
+
180
203
  export interface SecretOptions {
181
204
  factorySlug?: string;
182
205
  }
@@ -668,6 +691,40 @@ export class AgentComposeClient {
668
691
  return this.fetch(`/api/v1/factories/${encodeURIComponent(slug)}`, { method: "DELETE" });
669
692
  }
670
693
 
694
+ // ── Schedules ─────────────────────────────────────────────────────────────
695
+ // Cron schedules attached to a registered workflow. One workflow can have
696
+ // N schedules with distinct names + cadences; runs the schedule triggers
697
+ // are tagged with the schedule's id and name in their metadata.
698
+
699
+ /** List every schedule in a factory, with the engine-reported next/last
700
+ * fire times merged in. */
701
+ async listSchedules(factorySlug = "default"): Promise<ScheduleRow[]> {
702
+ const body = await this.fetch<{ schedules: ScheduleRow[] }>(
703
+ `/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules`,
704
+ );
705
+ return body.schedules;
706
+ }
707
+
708
+ /** Create a new schedule. `name` is per-factory unique; the server
709
+ * returns 409 on collision. */
710
+ createSchedule(payload: CreateScheduleInput): Promise<{ id: string; name: string; workflow: string; cron: string }> {
711
+ const factorySlug = payload.factorySlug ?? "default";
712
+ return this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules`, {
713
+ method: "POST",
714
+ body: { name: payload.name, workflow: payload.workflow, cron: payload.cron },
715
+ });
716
+ }
717
+
718
+ /** Delete a schedule by id. Best-effort: a transient engine error is
719
+ * logged server-side but the DB row is removed regardless — the boot
720
+ * reconciler reconverges on next start. */
721
+ deleteSchedule(id: string, factorySlug = "default"): Promise<void> {
722
+ return this.fetch(
723
+ `/api/v1/factories/${encodeURIComponent(factorySlug)}/schedules/${encodeURIComponent(id)}`,
724
+ { method: "DELETE" },
725
+ );
726
+ }
727
+
671
728
  // ── Secrets ────────────────────────────────────────────────────────────────
672
729
  // Scoped to (factory, workflow, key). Stored in GCP Secret Manager;
673
730
  // `factorySlug` defaults to `"default"`.
@@ -69,6 +69,7 @@ export function defineSandboxEnvironment(
69
69
  throw new Error(`defineSandboxEnvironment(${env.name}): 'setup' must be a function`);
70
70
  }
71
71
  return defineWorkflow<void, Record<string, unknown>>({
72
+ ...(env.description !== undefined ? { description: env.description } : {}),
72
73
  snapshots: env.snapshots ?? { saveLatest: true },
73
74
  memory: env.memory ?? false,
74
75
  run: async (_ctx, sandbox) => env.setup(sandbox),
@@ -74,6 +74,11 @@ export interface IOSchema {
74
74
  export type OutputSchema = IOSchema;
75
75
 
76
76
  export interface WorkflowMetadata {
77
+ /** One-line, human-readable description of what the workflow does.
78
+ * Surfaced on the dashboard template tile + run page header. Authors
79
+ * set it via `defineWorkflow({ description: "..." })` (either shape)
80
+ * or `defineSandboxEnvironment({ description: "..." })`. */
81
+ description?: string;
77
82
  networkPolicy?: SandboxNetworkPolicy;
78
83
  placeholders?: Record<string, string>;
79
84
  /** Input schema captured at bundle time from the workflow's
@@ -117,6 +122,7 @@ export interface WorkflowMetadata {
117
122
  */
118
123
  export function extractMetadata(source: Partial<WorkflowMetadata>): WorkflowMetadata {
119
124
  const out: WorkflowMetadata = {};
125
+ if (source.description !== undefined) out.description = source.description;
120
126
  if (source.networkPolicy !== undefined) out.networkPolicy = freezeMetadataValue(source.networkPolicy);
121
127
  if (source.placeholders !== undefined) out.placeholders = Object.freeze({ ...source.placeholders });
122
128
  if (source.inputSchema !== undefined) out.inputSchema = freezeMetadataValue(source.inputSchema);
@@ -89,6 +89,9 @@ export interface WorkflowDefinition<
89
89
  TOutput = unknown,
90
90
  TInput extends Record<string, unknown> = Record<string, unknown>,
91
91
  > {
92
+ /** One-line, human-readable description of what this workflow does.
93
+ * Surfaced on the dashboard template tile + run page header. */
94
+ description?: string;
92
95
  run: WorkflowFn<TOutput, TInput>;
93
96
  /**
94
97
  * All snapshot config — boot source plus capture mode.
@@ -43,6 +43,9 @@ export interface WorkflowBuilder<TInput, TCurrent> {
43
43
 
44
44
  export interface StepWorkflowDefinition<TInput, TOutput> {
45
45
  id: string;
46
+ /** One-line, human-readable description of what this workflow does.
47
+ * Surfaced on the dashboard template tile + run page header. */
48
+ description?: string;
46
49
  input: z.ZodType<TInput>;
47
50
  output: z.ZodType<TOutput>;
48
51
  networkPolicy?: SandboxNetworkPolicy;