@wave-ai-os/wave-cli 0.1.61 → 0.1.62

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/index.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  // src/index.ts
5
5
  var import_commander2 = require("commander");
6
- var import_zod19 = require("zod");
6
+ var import_zod20 = require("zod");
7
7
 
8
8
  // src/cli.ts
9
9
  var import_commander = require("commander");
@@ -1759,6 +1759,21 @@ async function runGraphqlMutationCommand(input) {
1759
1759
  variableTypes: input.variableTypes,
1760
1760
  selectionSet: input.selectionSet ?? "{ ok status errorCode data errors }"
1761
1761
  });
1762
+ if (result.envelope.ok && input.transformMutationPayload) {
1763
+ const envelopeData = result.envelope.data;
1764
+ if (!isRecord(envelopeData) || !Object.prototype.hasOwnProperty.call(envelopeData, input.field)) {
1765
+ throw new CliError({
1766
+ message: "Mutation response was missing its expected payload.",
1767
+ kind: "malformed_response",
1768
+ status: 502,
1769
+ exitCode: EXIT_CODES.networkOrUpstream
1770
+ });
1771
+ }
1772
+ result.envelope.data = {
1773
+ ...envelopeData,
1774
+ [input.field]: input.transformMutationPayload(envelopeData[input.field])
1775
+ };
1776
+ }
1762
1777
  printEnvelopeAndExit(result);
1763
1778
  } catch (error) {
1764
1779
  if (isEnvelopeEmittedSignal(error)) {
@@ -4216,7 +4231,7 @@ function findSkillById(id) {
4216
4231
  };
4217
4232
  }
4218
4233
  function registerSkillCommands(program) {
4219
- const skills = program.command("skills").description("Read Skill records");
4234
+ const skills = program.command("skills").description("Skill record operations");
4220
4235
  skills.command("list").description("List Skill records").option("--scope <scope>", "Filter skills by scope").option("--query <query>", "Filter skills by search query").option("--limit <limit>", "Limit skills returned").requiredOption("--json", "Emit the stable JSON envelope").action(async (opts, cmd) => {
4221
4236
  const context = await resolveCommandContext(cmd.optsWithGlobals());
4222
4237
  const organizationId = resolveOrganizationId(context.organizationId);
@@ -4242,7 +4257,7 @@ function registerSkillCommands(program) {
4242
4257
  isList: true
4243
4258
  });
4244
4259
  });
4245
- skills.command("show").description("Read one Skill record by id").requiredOption("--id <id>", "Skill id").requiredOption("--json", "Emit the stable JSON envelope").action(async (opts, cmd) => {
4260
+ skills.command("show").description("Read one persisted Skill record by id").requiredOption("--id <id>", "Skill id").requiredOption("--json", "Emit the stable JSON envelope").action(async (opts, cmd) => {
4246
4261
  const id = idSchema7.parse(opts.id);
4247
4262
  const context = await resolveCommandContext(cmd.optsWithGlobals());
4248
4263
  const organizationId = resolveOrganizationId(context.organizationId);
@@ -14886,6 +14901,259 @@ function registerAiNotesCommands(program) {
14886
14901
  });
14887
14902
  }
14888
14903
 
14904
+ // src/commands/atlasAuthoring.ts
14905
+ var import_zod19 = require("zod");
14906
+ var idSchema14 = import_zod19.z.string().trim().min(1);
14907
+ var idempotencyKeySchema = import_zod19.z.string().min(1).refine((value) => value.trim() === value, "Idempotency key must not have leading or trailing whitespace.");
14908
+ var skillScopeSchema = import_zod19.z.enum(["ADMIN_GLOBAL", "MEMBER_PERSONAL"]);
14909
+ var isoDateSchema = import_zod19.z.iso.date();
14910
+ var AGENT_SELECTION = `{
14911
+ id
14912
+ type
14913
+ name
14914
+ slug
14915
+ description
14916
+ notes
14917
+ status
14918
+ visibility
14919
+ model
14920
+ runWhenMentioned
14921
+ webAccessEnabled
14922
+ organizationId
14923
+ memberId
14924
+ createdAt
14925
+ updatedAt
14926
+ }`;
14927
+ var AUTOMATION_SELECTION = `{
14928
+ id
14929
+ type
14930
+ summary
14931
+ slug
14932
+ description
14933
+ notes
14934
+ status
14935
+ priority
14936
+ taskType
14937
+ aiTaskConfig
14938
+ organizationId
14939
+ memberId
14940
+ createdAt
14941
+ updatedAt
14942
+ }`;
14943
+ function asRecord9(value) {
14944
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
14945
+ }
14946
+ function asRequiredString(value) {
14947
+ if (typeof value !== "string") return null;
14948
+ const trimmed = value.trim();
14949
+ return trimmed.length > 0 ? trimmed : null;
14950
+ }
14951
+ function parseBooleanOption(value, optionName) {
14952
+ if (value === void 0) return void 0;
14953
+ if (value === "true") return true;
14954
+ if (value === "false") return false;
14955
+ throw new CliError({
14956
+ message: `Invalid ${optionName}: expected true or false.`,
14957
+ kind: "invalid_args",
14958
+ status: 400,
14959
+ exitCode: EXIT_CODES.invalidArgs
14960
+ });
14961
+ }
14962
+ function parseCommaSeparatedStrings(value) {
14963
+ if (value === void 0) return void 0;
14964
+ const entries = String(value).split(",").map((entry2) => entry2.trim()).filter((entry2) => entry2.length > 0);
14965
+ if (entries.length === 0) {
14966
+ throw new CliError({
14967
+ message: "--trusted-urls must include at least one URL.",
14968
+ kind: "invalid_args",
14969
+ status: 400,
14970
+ exitCode: EXIT_CODES.invalidArgs
14971
+ });
14972
+ }
14973
+ return entries;
14974
+ }
14975
+ function parseJson(value, optionName) {
14976
+ try {
14977
+ return JSON.parse(value);
14978
+ } catch (error) {
14979
+ throw new CliError({
14980
+ message: error instanceof Error ? `Invalid ${optionName}: ${error.message}` : `Invalid ${optionName}.`,
14981
+ kind: "invalid_args",
14982
+ status: 400,
14983
+ exitCode: EXIT_CODES.invalidArgs
14984
+ });
14985
+ }
14986
+ }
14987
+ function normalizePersistedCreatePayload(payload) {
14988
+ const mutation = asRecord9(payload);
14989
+ const mutationData = asRecord9(mutation?.data);
14990
+ const persisted = asRecord9(mutationData?.data) ?? mutationData;
14991
+ const attributes = asRecord9(persisted?.attributes);
14992
+ const meta = asRecord9(mutationData?.meta);
14993
+ const idempotency = asRecord9(meta?.atlas_idempotency);
14994
+ const id = asRequiredString(persisted?.id);
14995
+ const slug = asRequiredString(persisted?.slug) ?? asRequiredString(attributes?.slug);
14996
+ const replay = idempotency?.replay;
14997
+ if (!mutation || !mutationData || !persisted || !id || !slug || !idempotency || typeof replay !== "boolean") {
14998
+ throw new CliError({
14999
+ message: "Create response did not include persisted id/slug and idempotency metadata.",
15000
+ kind: "malformed_response",
15001
+ status: 502,
15002
+ exitCode: EXIT_CODES.networkOrUpstream
15003
+ });
15004
+ }
15005
+ return {
15006
+ ok: mutation.ok,
15007
+ status: mutation.status,
15008
+ errorCode: mutation.errorCode ?? null,
15009
+ errors: mutation.errors ?? null,
15010
+ persisted: { id, slug },
15011
+ idempotency: {
15012
+ object_type: asRequiredString(idempotency.object_type),
15013
+ id: asRequiredString(idempotency.id),
15014
+ slug: asRequiredString(idempotency.slug),
15015
+ idempotency_key: asRequiredString(idempotency.idempotency_key),
15016
+ fingerprint: asRequiredString(idempotency.fingerprint),
15017
+ replay,
15018
+ action: asRequiredString(idempotency.action)
15019
+ }
15020
+ };
15021
+ }
15022
+ function registerAtlasAuthoringCommands(program) {
15023
+ const agents = program.command("agents").description("Bounded Agent authoring operations");
15024
+ agents.command("create").description("Create an Agent through the API-owned createAgent contract").requiredOption("--idempotency-key <key>", "Required create idempotency key").option("--name <name>").option("--description <description>").option("--notes <notes>").option("--member-id <memberId>").option("--status <status>").option("--visibility <visibility>").option("--model <model>").option("--run-when-mentioned <boolean>", "true or false").option("--web-access-enabled <boolean>", "true or false").option("--trusted-urls <urls>", "Comma-separated trusted URLs").action(async (opts, cmd) => {
15025
+ const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15026
+ const runWhenMentioned = parseBooleanOption(opts.runWhenMentioned, "--run-when-mentioned");
15027
+ const webAccessEnabled = parseBooleanOption(opts.webAccessEnabled, "--web-access-enabled");
15028
+ const trustedUrls = parseCommaSeparatedStrings(opts.trustedUrls);
15029
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15030
+ const organizationId = resolveOrganizationId(context.organizationId);
15031
+ await runGraphqlMutationCommand({
15032
+ command: "agents.create",
15033
+ operationName: "AgentsCreate",
15034
+ runtimeOptions: context.runtimeOptions,
15035
+ field: "create_agent",
15036
+ variableTypes: {
15037
+ organization_id: "ID!",
15038
+ params: "CreateAgentParamsInput!",
15039
+ idempotency_key: "String!"
15040
+ },
15041
+ variables: {
15042
+ organization_id: organizationId,
15043
+ params: {
15044
+ agent: {
15045
+ ...opts.name !== void 0 ? { name: String(opts.name) } : {},
15046
+ ...opts.description !== void 0 ? { description: String(opts.description) } : {},
15047
+ ...opts.notes !== void 0 ? { notes: String(opts.notes) } : {},
15048
+ ...opts.memberId !== void 0 ? { member_id: idSchema14.parse(opts.memberId) } : {},
15049
+ ...opts.status !== void 0 ? { status: String(opts.status) } : {},
15050
+ ...opts.visibility !== void 0 ? { visibility: String(opts.visibility) } : {},
15051
+ ...opts.model !== void 0 ? { model: String(opts.model) } : {},
15052
+ ...runWhenMentioned !== void 0 ? { run_when_mentioned: runWhenMentioned } : {},
15053
+ ...webAccessEnabled !== void 0 ? { web_access_enabled: webAccessEnabled } : {},
15054
+ ...trustedUrls !== void 0 ? { trusted_urls: trustedUrls } : {}
15055
+ }
15056
+ },
15057
+ idempotency_key: idempotencyKey
15058
+ },
15059
+ transformMutationPayload: normalizePersistedCreatePayload
15060
+ });
15061
+ });
15062
+ agents.command("show").description("Read one persisted Agent by id").requiredOption("--id <id>", "Agent id").action(async (opts, cmd) => {
15063
+ const id = idSchema14.parse(opts.id);
15064
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15065
+ const organizationId = resolveOrganizationId(context.organizationId);
15066
+ await runGraphqlQueryCommand({
15067
+ command: "agents.show",
15068
+ operationName: "AgentsShow",
15069
+ runtimeOptions: context.runtimeOptions,
15070
+ field: "agent",
15071
+ variables: { organization_id: organizationId, id },
15072
+ variableTypes: { organization_id: "ID!", id: "ID!" },
15073
+ selectionSet: AGENT_SELECTION,
15074
+ isShow: true
15075
+ });
15076
+ });
15077
+ const automations = program.command("automations").description("Bounded Automation authoring operations");
15078
+ automations.command("create").description("Create an Automation through the API-owned createAutomation contract").requiredOption("--summary <summary>").requiredOption("--ai-task-config <json>", "Valid JSON for the API-owned ai_task_config field").requiredOption("--idempotency-key <key>", "Required create idempotency key").option("--description <description>").option("--notes <notes>").option("--member-id <memberId>").option("--status <status>").option("--priority <priority>").option("--due-date <date>", "ISO-8601 date (YYYY-MM-DD)").action(async (opts, cmd) => {
15079
+ const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15080
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15081
+ const organizationId = resolveOrganizationId(context.organizationId);
15082
+ await runGraphqlMutationCommand({
15083
+ command: "automations.create",
15084
+ operationName: "AutomationsCreate",
15085
+ runtimeOptions: context.runtimeOptions,
15086
+ field: "create_automation",
15087
+ variableTypes: {
15088
+ organization_id: "ID!",
15089
+ input: "CreateAutomationInput!",
15090
+ idempotency_key: "String!"
15091
+ },
15092
+ variables: {
15093
+ organization_id: organizationId,
15094
+ input: {
15095
+ summary: idSchema14.parse(opts.summary),
15096
+ ai_task_config: parseJson(String(opts.aiTaskConfig), "--ai-task-config"),
15097
+ ...opts.description !== void 0 ? { description: String(opts.description) } : {},
15098
+ ...opts.notes !== void 0 ? { notes: String(opts.notes) } : {},
15099
+ ...opts.memberId !== void 0 ? { member_id: idSchema14.parse(opts.memberId) } : {},
15100
+ ...opts.status !== void 0 ? { status: String(opts.status) } : {},
15101
+ ...opts.priority !== void 0 ? { priority: String(opts.priority) } : {},
15102
+ ...opts.dueDate !== void 0 ? { due_date: isoDateSchema.parse(opts.dueDate) } : {}
15103
+ },
15104
+ idempotency_key: idempotencyKey
15105
+ },
15106
+ transformMutationPayload: normalizePersistedCreatePayload
15107
+ });
15108
+ });
15109
+ automations.command("show").description("Read one persisted Automation by id").requiredOption("--id <id>", "Automation id").action(async (opts, cmd) => {
15110
+ const id = idSchema14.parse(opts.id);
15111
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15112
+ const organizationId = resolveOrganizationId(context.organizationId);
15113
+ await runGraphqlQueryCommand({
15114
+ command: "automations.show",
15115
+ operationName: "AutomationsShow",
15116
+ runtimeOptions: context.runtimeOptions,
15117
+ field: "automation",
15118
+ variables: { organization_id: organizationId, id },
15119
+ variableTypes: { organization_id: "ID!", id: "ID!" },
15120
+ selectionSet: AUTOMATION_SELECTION,
15121
+ isShow: true
15122
+ });
15123
+ });
15124
+ const skills = program.commands.find((command) => command.name() === "skills");
15125
+ if (!skills) {
15126
+ throw new Error("Skills command must be registered before Atlas authoring commands.");
15127
+ }
15128
+ skills.command("create").description("Create a Skill through the API-owned createSkill contract").requiredOption("--name <name>").requiredOption("--scope <scope>", "ADMIN_GLOBAL or MEMBER_PERSONAL").requiredOption("--idempotency-key <key>", "Required create idempotency key").option("--emoji <emoji>").option("--description <description>").action(async (opts, cmd) => {
15129
+ const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15130
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15131
+ const organizationId = resolveOrganizationId(context.organizationId);
15132
+ await runGraphqlMutationCommand({
15133
+ command: "skills.create",
15134
+ operationName: "SkillsCreate",
15135
+ runtimeOptions: context.runtimeOptions,
15136
+ field: "create_skill",
15137
+ variableTypes: {
15138
+ organization_id: "ID!",
15139
+ input: "CreateSkillInput!",
15140
+ idempotency_key: "String!"
15141
+ },
15142
+ variables: {
15143
+ organization_id: organizationId,
15144
+ input: {
15145
+ name: idSchema14.parse(opts.name),
15146
+ scope: skillScopeSchema.parse(opts.scope),
15147
+ ...opts.emoji !== void 0 ? { emoji: String(opts.emoji) } : {},
15148
+ ...opts.description !== void 0 ? { description: String(opts.description) } : {}
15149
+ },
15150
+ idempotency_key: idempotencyKey
15151
+ },
15152
+ transformMutationPayload: normalizePersistedCreatePayload
15153
+ });
15154
+ });
15155
+ }
15156
+
14889
15157
  // src/commands/discovery.ts
14890
15158
  var import_node_fs4 = require("fs");
14891
15159
  var import_node_path4 = require("path");
@@ -14906,6 +15174,8 @@ var PRIMARY_NAMESPACES = [
14906
15174
  "rocks",
14907
15175
  "meetings",
14908
15176
  "members",
15177
+ "agents",
15178
+ "automations",
14909
15179
  "skills",
14910
15180
  "teams",
14911
15181
  "issues",
@@ -15019,20 +15289,62 @@ var NAMESPACE_DOCS = {
15019
15289
  skills: {
15020
15290
  name: "skills",
15021
15291
  tier: "primary",
15022
- description: "Read-only Skill record proof surfaces.",
15292
+ description: "Skill record readback and bounded create operations.",
15023
15293
  examples: [
15024
15294
  "wave skills list --json",
15025
15295
  "wave skills list --scope ADMIN_GLOBAL --json",
15026
- "wave skills show --id 123 --json"
15296
+ "wave skills show --id 123 --json",
15297
+ 'wave skills create --name "Weekly planning" --scope MEMBER_PERSONAL --idempotency-key skill-create-001'
15027
15298
  ],
15028
15299
  schema: {
15029
15300
  output: "json-envelope-default",
15030
- readOnly: true,
15301
+ mutates: true,
15031
15302
  safety: [
15032
15303
  "Uses API-owned Skill GraphQL read fields only.",
15033
- "Does not create, update, destroy, archive, approve, or apply Skill records."
15304
+ "Create calls only createSkill with an explicit idempotency key.",
15305
+ "Skill create supports the API-defined ADMIN_GLOBAL and MEMBER_PERSONAL scopes.",
15306
+ "Does not update, destroy, archive, approve, or apply Skill records."
15034
15307
  ],
15035
- commands: ["list", "show"]
15308
+ commands: ["list", "show", "create"]
15309
+ }
15310
+ },
15311
+ agents: {
15312
+ name: "agents",
15313
+ tier: "primary",
15314
+ description: "Bounded Agent create and persisted readback operations.",
15315
+ examples: [
15316
+ 'wave agents create --name "Planning helper" --idempotency-key agent-create-001',
15317
+ "wave agents show --id 123"
15318
+ ],
15319
+ schema: {
15320
+ output: "json-envelope-default",
15321
+ mutates: true,
15322
+ safety: [
15323
+ "Create calls only createAgent with an explicit idempotency key.",
15324
+ "Create preserves API-owned defaults by sending only supplied typed Agent fields.",
15325
+ "Show uses the API-owned agent query by id; no slug fallback is implemented."
15326
+ ],
15327
+ commands: ["create", "show"]
15328
+ }
15329
+ },
15330
+ automations: {
15331
+ name: "automations",
15332
+ tier: "primary",
15333
+ description: "Bounded Automation create and persisted readback operations.",
15334
+ examples: [
15335
+ `wave automations create --summary "Weekly review" --ai-task-config '{"prompt":"Review tasks"}' --idempotency-key automation-create-001`,
15336
+ "wave automations show --id 123"
15337
+ ],
15338
+ schema: {
15339
+ output: "json-envelope-default",
15340
+ mutates: true,
15341
+ safety: [
15342
+ "Create calls only createAutomation with an explicit idempotency key.",
15343
+ "Only the API-defined ai_task_config field accepts validated JSON.",
15344
+ "Does not create a project Task, run an Automation, or invoke AI OS actions.",
15345
+ "Show uses the API-owned automation query by id; no slug fallback is implemented."
15346
+ ],
15347
+ commands: ["create", "show"]
15036
15348
  }
15037
15349
  },
15038
15350
  broadcast: {
@@ -15846,7 +16158,7 @@ function attachDiscoveryHelp(program) {
15846
16158
  }
15847
16159
 
15848
16160
  // src/version.ts
15849
- var CLI_VERSION = "0.1.61";
16161
+ var CLI_VERSION = "0.1.62";
15850
16162
 
15851
16163
  // src/cli.ts
15852
16164
  function buildCli(options) {
@@ -15901,6 +16213,7 @@ function buildCli(options) {
15901
16213
  registerMeetingCommands(program);
15902
16214
  registerMemberCommands(program);
15903
16215
  registerSkillCommands(program);
16216
+ registerAtlasAuthoringCommands(program);
15904
16217
  registerTeamCommands(program);
15905
16218
  registerOrganizationCommands(program);
15906
16219
  registerIssueCommands(program);
@@ -15980,13 +16293,13 @@ main().catch((error) => {
15980
16293
  });
15981
16294
  return;
15982
16295
  }
15983
- if (error instanceof import_zod19.ZodError || error instanceof import_commander2.InvalidArgumentError) {
16296
+ if (error instanceof import_zod20.ZodError || error instanceof import_commander2.InvalidArgumentError) {
15984
16297
  printCliFailure({
15985
16298
  status: 400,
15986
16299
  code: "invalid_args",
15987
16300
  message: "Invalid command arguments.",
15988
16301
  details: {
15989
- issues: error instanceof import_zod19.ZodError ? error.issues : [{ message: error.message, code: "invalid_argument" }]
16302
+ issues: error instanceof import_zod20.ZodError ? error.issues : [{ message: error.message, code: "invalid_argument" }]
15990
16303
  },
15991
16304
  exitCode: EXIT_CODES.invalidArgs
15992
16305
  });
package/dist/index.js CHANGED
@@ -1758,6 +1758,21 @@ async function runGraphqlMutationCommand(input) {
1758
1758
  variableTypes: input.variableTypes,
1759
1759
  selectionSet: input.selectionSet ?? "{ ok status errorCode data errors }"
1760
1760
  });
1761
+ if (result.envelope.ok && input.transformMutationPayload) {
1762
+ const envelopeData = result.envelope.data;
1763
+ if (!isRecord(envelopeData) || !Object.prototype.hasOwnProperty.call(envelopeData, input.field)) {
1764
+ throw new CliError({
1765
+ message: "Mutation response was missing its expected payload.",
1766
+ kind: "malformed_response",
1767
+ status: 502,
1768
+ exitCode: EXIT_CODES.networkOrUpstream
1769
+ });
1770
+ }
1771
+ result.envelope.data = {
1772
+ ...envelopeData,
1773
+ [input.field]: input.transformMutationPayload(envelopeData[input.field])
1774
+ };
1775
+ }
1761
1776
  printEnvelopeAndExit(result);
1762
1777
  } catch (error) {
1763
1778
  if (isEnvelopeEmittedSignal(error)) {
@@ -4215,7 +4230,7 @@ function findSkillById(id) {
4215
4230
  };
4216
4231
  }
4217
4232
  function registerSkillCommands(program) {
4218
- const skills = program.command("skills").description("Read Skill records");
4233
+ const skills = program.command("skills").description("Skill record operations");
4219
4234
  skills.command("list").description("List Skill records").option("--scope <scope>", "Filter skills by scope").option("--query <query>", "Filter skills by search query").option("--limit <limit>", "Limit skills returned").requiredOption("--json", "Emit the stable JSON envelope").action(async (opts, cmd) => {
4220
4235
  const context = await resolveCommandContext(cmd.optsWithGlobals());
4221
4236
  const organizationId = resolveOrganizationId(context.organizationId);
@@ -4241,7 +4256,7 @@ function registerSkillCommands(program) {
4241
4256
  isList: true
4242
4257
  });
4243
4258
  });
4244
- skills.command("show").description("Read one Skill record by id").requiredOption("--id <id>", "Skill id").requiredOption("--json", "Emit the stable JSON envelope").action(async (opts, cmd) => {
4259
+ skills.command("show").description("Read one persisted Skill record by id").requiredOption("--id <id>", "Skill id").requiredOption("--json", "Emit the stable JSON envelope").action(async (opts, cmd) => {
4245
4260
  const id = idSchema7.parse(opts.id);
4246
4261
  const context = await resolveCommandContext(cmd.optsWithGlobals());
4247
4262
  const organizationId = resolveOrganizationId(context.organizationId);
@@ -14885,6 +14900,259 @@ function registerAiNotesCommands(program) {
14885
14900
  });
14886
14901
  }
14887
14902
 
14903
+ // src/commands/atlasAuthoring.ts
14904
+ import { z as z19 } from "zod";
14905
+ var idSchema14 = z19.string().trim().min(1);
14906
+ var idempotencyKeySchema = z19.string().min(1).refine((value) => value.trim() === value, "Idempotency key must not have leading or trailing whitespace.");
14907
+ var skillScopeSchema = z19.enum(["ADMIN_GLOBAL", "MEMBER_PERSONAL"]);
14908
+ var isoDateSchema = z19.iso.date();
14909
+ var AGENT_SELECTION = `{
14910
+ id
14911
+ type
14912
+ name
14913
+ slug
14914
+ description
14915
+ notes
14916
+ status
14917
+ visibility
14918
+ model
14919
+ runWhenMentioned
14920
+ webAccessEnabled
14921
+ organizationId
14922
+ memberId
14923
+ createdAt
14924
+ updatedAt
14925
+ }`;
14926
+ var AUTOMATION_SELECTION = `{
14927
+ id
14928
+ type
14929
+ summary
14930
+ slug
14931
+ description
14932
+ notes
14933
+ status
14934
+ priority
14935
+ taskType
14936
+ aiTaskConfig
14937
+ organizationId
14938
+ memberId
14939
+ createdAt
14940
+ updatedAt
14941
+ }`;
14942
+ function asRecord9(value) {
14943
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
14944
+ }
14945
+ function asRequiredString(value) {
14946
+ if (typeof value !== "string") return null;
14947
+ const trimmed = value.trim();
14948
+ return trimmed.length > 0 ? trimmed : null;
14949
+ }
14950
+ function parseBooleanOption(value, optionName) {
14951
+ if (value === void 0) return void 0;
14952
+ if (value === "true") return true;
14953
+ if (value === "false") return false;
14954
+ throw new CliError({
14955
+ message: `Invalid ${optionName}: expected true or false.`,
14956
+ kind: "invalid_args",
14957
+ status: 400,
14958
+ exitCode: EXIT_CODES.invalidArgs
14959
+ });
14960
+ }
14961
+ function parseCommaSeparatedStrings(value) {
14962
+ if (value === void 0) return void 0;
14963
+ const entries = String(value).split(",").map((entry2) => entry2.trim()).filter((entry2) => entry2.length > 0);
14964
+ if (entries.length === 0) {
14965
+ throw new CliError({
14966
+ message: "--trusted-urls must include at least one URL.",
14967
+ kind: "invalid_args",
14968
+ status: 400,
14969
+ exitCode: EXIT_CODES.invalidArgs
14970
+ });
14971
+ }
14972
+ return entries;
14973
+ }
14974
+ function parseJson(value, optionName) {
14975
+ try {
14976
+ return JSON.parse(value);
14977
+ } catch (error) {
14978
+ throw new CliError({
14979
+ message: error instanceof Error ? `Invalid ${optionName}: ${error.message}` : `Invalid ${optionName}.`,
14980
+ kind: "invalid_args",
14981
+ status: 400,
14982
+ exitCode: EXIT_CODES.invalidArgs
14983
+ });
14984
+ }
14985
+ }
14986
+ function normalizePersistedCreatePayload(payload) {
14987
+ const mutation = asRecord9(payload);
14988
+ const mutationData = asRecord9(mutation?.data);
14989
+ const persisted = asRecord9(mutationData?.data) ?? mutationData;
14990
+ const attributes = asRecord9(persisted?.attributes);
14991
+ const meta = asRecord9(mutationData?.meta);
14992
+ const idempotency = asRecord9(meta?.atlas_idempotency);
14993
+ const id = asRequiredString(persisted?.id);
14994
+ const slug = asRequiredString(persisted?.slug) ?? asRequiredString(attributes?.slug);
14995
+ const replay = idempotency?.replay;
14996
+ if (!mutation || !mutationData || !persisted || !id || !slug || !idempotency || typeof replay !== "boolean") {
14997
+ throw new CliError({
14998
+ message: "Create response did not include persisted id/slug and idempotency metadata.",
14999
+ kind: "malformed_response",
15000
+ status: 502,
15001
+ exitCode: EXIT_CODES.networkOrUpstream
15002
+ });
15003
+ }
15004
+ return {
15005
+ ok: mutation.ok,
15006
+ status: mutation.status,
15007
+ errorCode: mutation.errorCode ?? null,
15008
+ errors: mutation.errors ?? null,
15009
+ persisted: { id, slug },
15010
+ idempotency: {
15011
+ object_type: asRequiredString(idempotency.object_type),
15012
+ id: asRequiredString(idempotency.id),
15013
+ slug: asRequiredString(idempotency.slug),
15014
+ idempotency_key: asRequiredString(idempotency.idempotency_key),
15015
+ fingerprint: asRequiredString(idempotency.fingerprint),
15016
+ replay,
15017
+ action: asRequiredString(idempotency.action)
15018
+ }
15019
+ };
15020
+ }
15021
+ function registerAtlasAuthoringCommands(program) {
15022
+ const agents = program.command("agents").description("Bounded Agent authoring operations");
15023
+ agents.command("create").description("Create an Agent through the API-owned createAgent contract").requiredOption("--idempotency-key <key>", "Required create idempotency key").option("--name <name>").option("--description <description>").option("--notes <notes>").option("--member-id <memberId>").option("--status <status>").option("--visibility <visibility>").option("--model <model>").option("--run-when-mentioned <boolean>", "true or false").option("--web-access-enabled <boolean>", "true or false").option("--trusted-urls <urls>", "Comma-separated trusted URLs").action(async (opts, cmd) => {
15024
+ const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15025
+ const runWhenMentioned = parseBooleanOption(opts.runWhenMentioned, "--run-when-mentioned");
15026
+ const webAccessEnabled = parseBooleanOption(opts.webAccessEnabled, "--web-access-enabled");
15027
+ const trustedUrls = parseCommaSeparatedStrings(opts.trustedUrls);
15028
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15029
+ const organizationId = resolveOrganizationId(context.organizationId);
15030
+ await runGraphqlMutationCommand({
15031
+ command: "agents.create",
15032
+ operationName: "AgentsCreate",
15033
+ runtimeOptions: context.runtimeOptions,
15034
+ field: "create_agent",
15035
+ variableTypes: {
15036
+ organization_id: "ID!",
15037
+ params: "CreateAgentParamsInput!",
15038
+ idempotency_key: "String!"
15039
+ },
15040
+ variables: {
15041
+ organization_id: organizationId,
15042
+ params: {
15043
+ agent: {
15044
+ ...opts.name !== void 0 ? { name: String(opts.name) } : {},
15045
+ ...opts.description !== void 0 ? { description: String(opts.description) } : {},
15046
+ ...opts.notes !== void 0 ? { notes: String(opts.notes) } : {},
15047
+ ...opts.memberId !== void 0 ? { member_id: idSchema14.parse(opts.memberId) } : {},
15048
+ ...opts.status !== void 0 ? { status: String(opts.status) } : {},
15049
+ ...opts.visibility !== void 0 ? { visibility: String(opts.visibility) } : {},
15050
+ ...opts.model !== void 0 ? { model: String(opts.model) } : {},
15051
+ ...runWhenMentioned !== void 0 ? { run_when_mentioned: runWhenMentioned } : {},
15052
+ ...webAccessEnabled !== void 0 ? { web_access_enabled: webAccessEnabled } : {},
15053
+ ...trustedUrls !== void 0 ? { trusted_urls: trustedUrls } : {}
15054
+ }
15055
+ },
15056
+ idempotency_key: idempotencyKey
15057
+ },
15058
+ transformMutationPayload: normalizePersistedCreatePayload
15059
+ });
15060
+ });
15061
+ agents.command("show").description("Read one persisted Agent by id").requiredOption("--id <id>", "Agent id").action(async (opts, cmd) => {
15062
+ const id = idSchema14.parse(opts.id);
15063
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15064
+ const organizationId = resolveOrganizationId(context.organizationId);
15065
+ await runGraphqlQueryCommand({
15066
+ command: "agents.show",
15067
+ operationName: "AgentsShow",
15068
+ runtimeOptions: context.runtimeOptions,
15069
+ field: "agent",
15070
+ variables: { organization_id: organizationId, id },
15071
+ variableTypes: { organization_id: "ID!", id: "ID!" },
15072
+ selectionSet: AGENT_SELECTION,
15073
+ isShow: true
15074
+ });
15075
+ });
15076
+ const automations = program.command("automations").description("Bounded Automation authoring operations");
15077
+ automations.command("create").description("Create an Automation through the API-owned createAutomation contract").requiredOption("--summary <summary>").requiredOption("--ai-task-config <json>", "Valid JSON for the API-owned ai_task_config field").requiredOption("--idempotency-key <key>", "Required create idempotency key").option("--description <description>").option("--notes <notes>").option("--member-id <memberId>").option("--status <status>").option("--priority <priority>").option("--due-date <date>", "ISO-8601 date (YYYY-MM-DD)").action(async (opts, cmd) => {
15078
+ const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15079
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15080
+ const organizationId = resolveOrganizationId(context.organizationId);
15081
+ await runGraphqlMutationCommand({
15082
+ command: "automations.create",
15083
+ operationName: "AutomationsCreate",
15084
+ runtimeOptions: context.runtimeOptions,
15085
+ field: "create_automation",
15086
+ variableTypes: {
15087
+ organization_id: "ID!",
15088
+ input: "CreateAutomationInput!",
15089
+ idempotency_key: "String!"
15090
+ },
15091
+ variables: {
15092
+ organization_id: organizationId,
15093
+ input: {
15094
+ summary: idSchema14.parse(opts.summary),
15095
+ ai_task_config: parseJson(String(opts.aiTaskConfig), "--ai-task-config"),
15096
+ ...opts.description !== void 0 ? { description: String(opts.description) } : {},
15097
+ ...opts.notes !== void 0 ? { notes: String(opts.notes) } : {},
15098
+ ...opts.memberId !== void 0 ? { member_id: idSchema14.parse(opts.memberId) } : {},
15099
+ ...opts.status !== void 0 ? { status: String(opts.status) } : {},
15100
+ ...opts.priority !== void 0 ? { priority: String(opts.priority) } : {},
15101
+ ...opts.dueDate !== void 0 ? { due_date: isoDateSchema.parse(opts.dueDate) } : {}
15102
+ },
15103
+ idempotency_key: idempotencyKey
15104
+ },
15105
+ transformMutationPayload: normalizePersistedCreatePayload
15106
+ });
15107
+ });
15108
+ automations.command("show").description("Read one persisted Automation by id").requiredOption("--id <id>", "Automation id").action(async (opts, cmd) => {
15109
+ const id = idSchema14.parse(opts.id);
15110
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15111
+ const organizationId = resolveOrganizationId(context.organizationId);
15112
+ await runGraphqlQueryCommand({
15113
+ command: "automations.show",
15114
+ operationName: "AutomationsShow",
15115
+ runtimeOptions: context.runtimeOptions,
15116
+ field: "automation",
15117
+ variables: { organization_id: organizationId, id },
15118
+ variableTypes: { organization_id: "ID!", id: "ID!" },
15119
+ selectionSet: AUTOMATION_SELECTION,
15120
+ isShow: true
15121
+ });
15122
+ });
15123
+ const skills = program.commands.find((command) => command.name() === "skills");
15124
+ if (!skills) {
15125
+ throw new Error("Skills command must be registered before Atlas authoring commands.");
15126
+ }
15127
+ skills.command("create").description("Create a Skill through the API-owned createSkill contract").requiredOption("--name <name>").requiredOption("--scope <scope>", "ADMIN_GLOBAL or MEMBER_PERSONAL").requiredOption("--idempotency-key <key>", "Required create idempotency key").option("--emoji <emoji>").option("--description <description>").action(async (opts, cmd) => {
15128
+ const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15129
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
15130
+ const organizationId = resolveOrganizationId(context.organizationId);
15131
+ await runGraphqlMutationCommand({
15132
+ command: "skills.create",
15133
+ operationName: "SkillsCreate",
15134
+ runtimeOptions: context.runtimeOptions,
15135
+ field: "create_skill",
15136
+ variableTypes: {
15137
+ organization_id: "ID!",
15138
+ input: "CreateSkillInput!",
15139
+ idempotency_key: "String!"
15140
+ },
15141
+ variables: {
15142
+ organization_id: organizationId,
15143
+ input: {
15144
+ name: idSchema14.parse(opts.name),
15145
+ scope: skillScopeSchema.parse(opts.scope),
15146
+ ...opts.emoji !== void 0 ? { emoji: String(opts.emoji) } : {},
15147
+ ...opts.description !== void 0 ? { description: String(opts.description) } : {}
15148
+ },
15149
+ idempotency_key: idempotencyKey
15150
+ },
15151
+ transformMutationPayload: normalizePersistedCreatePayload
15152
+ });
15153
+ });
15154
+ }
15155
+
14888
15156
  // src/commands/discovery.ts
14889
15157
  import { existsSync as existsSync3, readFileSync } from "fs";
14890
15158
  import { join as join3 } from "path";
@@ -14905,6 +15173,8 @@ var PRIMARY_NAMESPACES = [
14905
15173
  "rocks",
14906
15174
  "meetings",
14907
15175
  "members",
15176
+ "agents",
15177
+ "automations",
14908
15178
  "skills",
14909
15179
  "teams",
14910
15180
  "issues",
@@ -15018,20 +15288,62 @@ var NAMESPACE_DOCS = {
15018
15288
  skills: {
15019
15289
  name: "skills",
15020
15290
  tier: "primary",
15021
- description: "Read-only Skill record proof surfaces.",
15291
+ description: "Skill record readback and bounded create operations.",
15022
15292
  examples: [
15023
15293
  "wave skills list --json",
15024
15294
  "wave skills list --scope ADMIN_GLOBAL --json",
15025
- "wave skills show --id 123 --json"
15295
+ "wave skills show --id 123 --json",
15296
+ 'wave skills create --name "Weekly planning" --scope MEMBER_PERSONAL --idempotency-key skill-create-001'
15026
15297
  ],
15027
15298
  schema: {
15028
15299
  output: "json-envelope-default",
15029
- readOnly: true,
15300
+ mutates: true,
15030
15301
  safety: [
15031
15302
  "Uses API-owned Skill GraphQL read fields only.",
15032
- "Does not create, update, destroy, archive, approve, or apply Skill records."
15303
+ "Create calls only createSkill with an explicit idempotency key.",
15304
+ "Skill create supports the API-defined ADMIN_GLOBAL and MEMBER_PERSONAL scopes.",
15305
+ "Does not update, destroy, archive, approve, or apply Skill records."
15033
15306
  ],
15034
- commands: ["list", "show"]
15307
+ commands: ["list", "show", "create"]
15308
+ }
15309
+ },
15310
+ agents: {
15311
+ name: "agents",
15312
+ tier: "primary",
15313
+ description: "Bounded Agent create and persisted readback operations.",
15314
+ examples: [
15315
+ 'wave agents create --name "Planning helper" --idempotency-key agent-create-001',
15316
+ "wave agents show --id 123"
15317
+ ],
15318
+ schema: {
15319
+ output: "json-envelope-default",
15320
+ mutates: true,
15321
+ safety: [
15322
+ "Create calls only createAgent with an explicit idempotency key.",
15323
+ "Create preserves API-owned defaults by sending only supplied typed Agent fields.",
15324
+ "Show uses the API-owned agent query by id; no slug fallback is implemented."
15325
+ ],
15326
+ commands: ["create", "show"]
15327
+ }
15328
+ },
15329
+ automations: {
15330
+ name: "automations",
15331
+ tier: "primary",
15332
+ description: "Bounded Automation create and persisted readback operations.",
15333
+ examples: [
15334
+ `wave automations create --summary "Weekly review" --ai-task-config '{"prompt":"Review tasks"}' --idempotency-key automation-create-001`,
15335
+ "wave automations show --id 123"
15336
+ ],
15337
+ schema: {
15338
+ output: "json-envelope-default",
15339
+ mutates: true,
15340
+ safety: [
15341
+ "Create calls only createAutomation with an explicit idempotency key.",
15342
+ "Only the API-defined ai_task_config field accepts validated JSON.",
15343
+ "Does not create a project Task, run an Automation, or invoke AI OS actions.",
15344
+ "Show uses the API-owned automation query by id; no slug fallback is implemented."
15345
+ ],
15346
+ commands: ["create", "show"]
15035
15347
  }
15036
15348
  },
15037
15349
  broadcast: {
@@ -15845,7 +16157,7 @@ function attachDiscoveryHelp(program) {
15845
16157
  }
15846
16158
 
15847
16159
  // src/version.ts
15848
- var CLI_VERSION = "0.1.61";
16160
+ var CLI_VERSION = "0.1.62";
15849
16161
 
15850
16162
  // src/cli.ts
15851
16163
  function buildCli(options) {
@@ -15900,6 +16212,7 @@ function buildCli(options) {
15900
16212
  registerMeetingCommands(program);
15901
16213
  registerMemberCommands(program);
15902
16214
  registerSkillCommands(program);
16215
+ registerAtlasAuthoringCommands(program);
15903
16216
  registerTeamCommands(program);
15904
16217
  registerOrganizationCommands(program);
15905
16218
  registerIssueCommands(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wave-ai-os/wave-cli",
3
- "version": "0.1.61",
3
+ "version": "0.1.62",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "wave": "dist/index.js"