@wave-ai-os/wave-cli 0.1.63 → 0.1.66

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 CHANGED
@@ -39,7 +39,7 @@ Secure stdin auth/context examples:
39
39
  ```bash
40
40
  printf '%s' "token-value" | wave --token-stdin --base-url https://api.example.com --organization-id 42 tasks list --page 1 --per 10
41
41
 
42
- printf '%s' '{"token":"token-value","baseUrl":"https://api.example.com","organizationId":"42","agentName":"atlas"}' \
42
+ printf '%s' '{"token":"token-value","baseUrl":"https://api.example.com","agentName":"atlas"}' \
43
43
  | wave --auth-json-stdin tasks list --page 1 --per 10
44
44
  ```
45
45
 
@@ -72,10 +72,7 @@ Required (from flags, stdin, env, config, or stored credentials):
72
72
  - `WAVE_API_BASE_URL`
73
73
 
74
74
  Organization-scoped data commands use the organization certified by the
75
- authenticated CLI token. `--organization-id` is the only local override. The
76
- CLI intentionally ignores `WAVE_ORGANIZATION_ID`, `WAVE_ORG_ID`, stdin, and
77
- stored config organization values as automatic scopes so a stale local value
78
- cannot select a different organization.
75
+ authenticated CLI token. `--organization-id` is the only local override.
79
76
 
80
77
  Optional env:
81
78
 
@@ -103,7 +100,6 @@ Config files are JSON objects using the same keys accepted by `--auth-json-stdin
103
100
  {
104
101
  "token": "token-value",
105
102
  "baseUrl": "https://api.example.com",
106
- "organizationId": "42",
107
103
  "agentName": "atlas"
108
104
  }
109
105
  ```
package/dist/index.cjs CHANGED
@@ -128,9 +128,7 @@ function getConfig(options) {
128
128
  const parsed = configSchema.safeParse({
129
129
  baseUrl,
130
130
  token,
131
- organizationId: toOptionalNonEmpty(
132
- options.organizationId ?? process.env.WAVE_ORGANIZATION_ID ?? process.env.WAVE_ORG_ID
133
- ),
131
+ organizationId: toOptionalNonEmpty(options.organizationId),
134
132
  timeoutMs: parseTimeoutMs(options.timeoutMs ?? process.env.WAVE_TIMEOUT_MS),
135
133
  debug: options.debug ?? parseDebug(process.env.WAVE_DEBUG),
136
134
  agentName: toOptionalNonEmpty(options.agentName ?? process.env.WAVE_AGENT_NAME),
@@ -2187,7 +2185,6 @@ function parseAuthJson(raw) {
2187
2185
  return {
2188
2186
  token: normalize3(obj.token),
2189
2187
  baseUrl: normalize3(obj.baseUrl ?? obj.base_url),
2190
- organizationId: normalize3(obj.organizationId ?? obj.organization_id),
2191
2188
  timeoutMs: typeof obj.timeoutMs === "number" || typeof obj.timeoutMs === "string" ? obj.timeoutMs : typeof obj.timeout_ms === "number" || typeof obj.timeout_ms === "string" ? obj.timeout_ms : void 0,
2192
2189
  debug: parseBool(obj.debug),
2193
2190
  agentName: normalize3(obj.agentName ?? obj.agent_name),
@@ -2270,7 +2267,6 @@ function resolveAuthToken(options, stdin, config, env) {
2270
2267
  { token: normalize3(options.token), source: "flag" },
2271
2268
  { token: normalize3(stdin.token), source: "stdin" },
2272
2269
  { token: normalize3(env.WAVE_API_TOKEN), source: "env" },
2273
- { token: normalize3(config.token), source: "config" },
2274
2270
  { token: normalize3(config.token), source: "config" }
2275
2271
  ];
2276
2272
  return candidates.find((candidate) => candidate.token) ?? { source: "none" };
@@ -2283,18 +2279,8 @@ function resolveFromSources(options, stdin, config, env) {
2283
2279
  normalize3(env.WAVE_API_URL),
2284
2280
  normalize3(config.baseUrl)
2285
2281
  );
2286
- const organizationCandidates = [
2287
- { organizationId: normalize3(options.organizationId), source: "flag" },
2288
- { organizationId: normalize3(stdin.organizationId), source: "stdin" },
2289
- { organizationId: normalize3(env.WAVE_ORGANIZATION_ID), source: "env" },
2290
- { organizationId: normalize3(env.WAVE_ORG_ID), source: "env" },
2291
- { organizationId: normalize3(config.organizationId), source: "config" }
2292
- ];
2293
- const resolvedOrganization = organizationCandidates.find((candidate) => candidate.organizationId) ?? {
2294
- organizationId: void 0,
2295
- source: "none"
2296
- };
2297
- const organizationId = resolvedOrganization.organizationId;
2282
+ const organizationId = normalize3(options.organizationId);
2283
+ const organizationIdSource = organizationId ? "flag" : "none";
2298
2284
  const timeoutMs = firstDefined(options.timeoutMs, stdin.timeoutMs, env.WAVE_TIMEOUT_MS, config.timeoutMs);
2299
2285
  const debug = firstDefined(
2300
2286
  options.debug,
@@ -2383,7 +2369,7 @@ function resolveFromSources(options, stdin, config, env) {
2383
2369
  const resolvedAuth = resolveAuthToken(options, stdin, config, env);
2384
2370
  return {
2385
2371
  organizationId,
2386
- organizationIdSource: resolvedOrganization.source,
2372
+ organizationIdSource,
2387
2373
  runtimeOptions: {
2388
2374
  token: resolvedAuth.token,
2389
2375
  tokenSource: resolvedAuth.token ? resolvedAuth.source : "none",
@@ -2523,7 +2509,9 @@ async function resolveCommandContext(options) {
2523
2509
  function organizationIdFromCliAuthStatus(data) {
2524
2510
  const status = data.cliAuthStatus;
2525
2511
  if (!status || typeof status !== "object" || Array.isArray(status)) return void 0;
2526
- const organization = status.organization;
2512
+ const cliAuthStatus = status;
2513
+ if (cliAuthStatus.authenticated !== true) return void 0;
2514
+ const organization = cliAuthStatus.organization;
2527
2515
  if (!organization || typeof organization !== "object" || Array.isArray(organization)) return void 0;
2528
2516
  return normalize3(organization.id);
2529
2517
  }
@@ -14460,7 +14448,7 @@ async function runDatasheetsQuery(cmd, config) {
14460
14448
  });
14461
14449
  }
14462
14450
  async function runDatasheetsMutation(cmd, opts, config) {
14463
- const context = await resolveCommandContext(cmd.optsWithGlobals());
14451
+ const context = config.organizationContext === "optional" ? await resolveUnscopedCommandContext(cmd.optsWithGlobals()) : await resolveCommandContext(cmd.optsWithGlobals());
14464
14452
  const variables = config.organizationContext === "optional" ? context.organizationId ? { organization_id: context.organizationId } : {} : { organization_id: resolveOrganizationId(context.organizationId) };
14465
14453
  for (const id of config.requiredIds ?? []) {
14466
14454
  variables[id.variable] = requireNonEmpty(opts[id.option], id.label, config.command);
@@ -14497,7 +14485,7 @@ async function runDatasheetsMutation(cmd, opts, config) {
14497
14485
  runtimeOptions: context.runtimeOptions,
14498
14486
  field: config.field,
14499
14487
  variables: normalizeGraphqlVariables2(variables),
14500
- variableTypes: { organization_id: "ID!" },
14488
+ variableTypes: config.organizationContext === "optional" && !context.organizationId ? {} : { organization_id: "ID!" },
14501
14489
  selectionSet: DATASHEET_MUTATION_SELECTION
14502
14490
  });
14503
14491
  }
@@ -14789,115 +14777,6 @@ function registerDatasheetsCommands(program) {
14789
14777
  });
14790
14778
  }
14791
14779
 
14792
- // src/commands/aiNotes.ts
14793
- var AI_NOTE_SAFE_FIELDS = [
14794
- "id",
14795
- "slug",
14796
- "title",
14797
- "status",
14798
- "visibility",
14799
- "sourceType",
14800
- "sourceReference",
14801
- "ownerMemberId",
14802
- "scheduledStartAt",
14803
- "scheduledEndAt",
14804
- "createdAt",
14805
- "updatedAt"
14806
- ];
14807
- var AI_NOTE_SELECTION = `{ ${AI_NOTE_SAFE_FIELDS.join(" ")} }`;
14808
- var AI_NOTES_SELECTION = AI_NOTE_SELECTION;
14809
- function pickSafeAiNoteFields(value) {
14810
- if (!value || typeof value !== "object" || Array.isArray(value)) {
14811
- return null;
14812
- }
14813
- const record = value;
14814
- const safe = {};
14815
- for (const field of AI_NOTE_SAFE_FIELDS) {
14816
- if (Object.prototype.hasOwnProperty.call(record, field)) {
14817
- safe[field] = record[field];
14818
- }
14819
- }
14820
- return safe;
14821
- }
14822
- function projectAiNotesPayload(payload) {
14823
- if (Array.isArray(payload)) {
14824
- return payload.map((item) => pickSafeAiNoteFields(item)).filter(Boolean);
14825
- }
14826
- if (!payload || typeof payload !== "object") {
14827
- return payload;
14828
- }
14829
- return pickSafeAiNoteFields(payload);
14830
- }
14831
- function showVariables(opts) {
14832
- const id = typeof opts.id === "string" && opts.id.trim() !== "" ? opts.id.trim() : void 0;
14833
- const slug = typeof opts.slug === "string" && opts.slug.trim() !== "" ? opts.slug.trim() : void 0;
14834
- if (!id && !slug || id && slug) {
14835
- throw new CliError({
14836
- message: "Provide exactly one AI Note identifier: --id or --slug.",
14837
- kind: "invalid_args",
14838
- status: 400,
14839
- exitCode: EXIT_CODES.invalidArgs,
14840
- details: { requiredOneOf: ["--id", "--slug"] }
14841
- });
14842
- }
14843
- return id ? { id } : { slug };
14844
- }
14845
- async function runAiNotesQuery(cmd, config) {
14846
- const context = await resolveCommandContext(cmd.optsWithGlobals());
14847
- await runGraphqlQueryCommand({
14848
- command: config.command,
14849
- operationName: config.operationName,
14850
- runtimeOptions: context.runtimeOptions,
14851
- field: config.field,
14852
- variables: normalizeGraphqlVariables2({
14853
- organization_id: resolveOrganizationId(context.organizationId),
14854
- ...config.variables
14855
- }),
14856
- variableTypes: config.variableTypes,
14857
- selectionSet: config.selectionSet,
14858
- isList: config.isList,
14859
- isShow: config.isShow,
14860
- transformData: projectAiNotesPayload
14861
- });
14862
- }
14863
- function registerAiNotesCommands(program) {
14864
- const aiNotes = program.command("ai-notes").description("AI Notes read-only list and detail metadata");
14865
- aiNotes.command("list").description("Read safe AI Note metadata without transcripts or provider payloads").option("--page <page>").option("--per <per>").action(async (opts, cmd) => {
14866
- await runAiNotesQuery(cmd, {
14867
- command: "ai-notes.list",
14868
- operationName: "AiNotes",
14869
- field: "ai_notes",
14870
- variables: {
14871
- page: opts.page,
14872
- per: opts.per
14873
- },
14874
- variableTypes: {
14875
- organization_id: "ID!",
14876
- page: "Int",
14877
- per: "Int"
14878
- },
14879
- selectionSet: AI_NOTES_SELECTION,
14880
- isList: true
14881
- });
14882
- });
14883
- aiNotes.command("show").description("Read safe AI Note detail metadata by id or slug").option("--id <id>").option("--slug <slug>").action(async (opts, cmd) => {
14884
- const variables = showVariables(opts);
14885
- await runAiNotesQuery(cmd, {
14886
- command: "ai-notes.show",
14887
- operationName: "AiNote",
14888
- field: "ai_note",
14889
- variables,
14890
- variableTypes: {
14891
- organization_id: "ID!",
14892
- ...variables.id ? { id: "ID!" } : {},
14893
- ...variables.slug ? { slug: "String!" } : {}
14894
- },
14895
- selectionSet: AI_NOTE_SELECTION,
14896
- isShow: true
14897
- });
14898
- });
14899
- }
14900
-
14901
14780
  // src/commands/atlasAuthoring.ts
14902
14781
  var import_zod19 = require("zod");
14903
14782
  var idSchema14 = import_zod19.z.string().trim().min(1);
@@ -15072,7 +14951,7 @@ function registerAtlasAuthoringCommands(program) {
15072
14951
  });
15073
14952
  });
15074
14953
  const automations = program.command("automations").description("Bounded Automation authoring operations");
15075
- 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) => {
14954
+ 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("--agent-id <agentId>", "Optional executor Agent id for a repeat Automation").option("--status <status>").option("--priority <priority>").option("--due-date <date>", "ISO-8601 date (YYYY-MM-DD)").action(async (opts, cmd) => {
15076
14955
  const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15077
14956
  const context = await resolveCommandContext(cmd.optsWithGlobals());
15078
14957
  const organizationId = resolveOrganizationId(context.organizationId);
@@ -15094,6 +14973,7 @@ function registerAtlasAuthoringCommands(program) {
15094
14973
  ...opts.description !== void 0 ? { description: String(opts.description) } : {},
15095
14974
  ...opts.notes !== void 0 ? { notes: String(opts.notes) } : {},
15096
14975
  ...opts.memberId !== void 0 ? { member_id: idSchema14.parse(opts.memberId) } : {},
14976
+ ...opts.agentId !== void 0 ? { agentId: idSchema14.parse(opts.agentId) } : {},
15097
14977
  ...opts.status !== void 0 ? { status: String(opts.status) } : {},
15098
14978
  ...opts.priority !== void 0 ? { priority: String(opts.priority) } : {},
15099
14979
  ...opts.dueDate !== void 0 ? { due_date: isoDateSchema.parse(opts.dueDate) } : {}
@@ -15164,7 +15044,6 @@ var PRIMARY_NAMESPACES = [
15164
15044
  "planner",
15165
15045
  "mail",
15166
15046
  "datasheets",
15167
- "ai-notes",
15168
15047
  "phantom",
15169
15048
  "tasks",
15170
15049
  "projects",
@@ -15329,7 +15208,7 @@ var NAMESPACE_DOCS = {
15329
15208
  tier: "primary",
15330
15209
  description: "Bounded Automation create and persisted readback operations.",
15331
15210
  examples: [
15332
- `wave automations create --summary "Weekly review" --ai-task-config '{"prompt":"Review tasks"}' --idempotency-key automation-create-001`,
15211
+ `wave automations create --summary "Weekly review" --agent-id 123 --ai-task-config '{"cycle":"repeat","repeatSchedule":{"interval":1,"frequency":"week","weekdays":[1,3],"at":"2:30 PM","starting":"2026-07-20T00:00:00.000Z","ending":"never","endingRuns":1,"endingDate":null,"timezone":"America/Phoenix"}}' --idempotency-key automation-create-001`,
15333
15212
  "wave automations show --id 123"
15334
15213
  ],
15335
15214
  schema: {
@@ -15338,6 +15217,7 @@ var NAMESPACE_DOCS = {
15338
15217
  safety: [
15339
15218
  "Create calls only createAutomation with an explicit idempotency key.",
15340
15219
  "Only the API-defined ai_task_config field accepts validated JSON.",
15220
+ "Optional executor Agent linkage is sent only through the API-defined top-level agentId input.",
15341
15221
  "Does not create a project Task, run an Automation, or invoke AI OS actions.",
15342
15222
  "Show uses the API-owned automation query by id; no slug fallback is implemented."
15343
15223
  ],
@@ -15599,26 +15479,6 @@ var NAMESPACE_DOCS = {
15599
15479
  ]
15600
15480
  }
15601
15481
  },
15602
- "ai-notes": {
15603
- name: "ai-notes",
15604
- tier: "primary",
15605
- description: "AI Notes read-only list and detail metadata for CLI-backed Atlas and harness inspection.",
15606
- examples: [
15607
- "wave ai-notes list --page 1 --per 20",
15608
- "wave ai-notes show --id note_123",
15609
- "wave ai-notes show --slug weekly-summary"
15610
- ],
15611
- schema: {
15612
- output: "json-envelope-default",
15613
- readOnly: true,
15614
- safety: [
15615
- "Uses API-owned GraphQL read fields aiNotes and aiNote.",
15616
- "List/show output is limited to safe AI Note identifiers, title, status, visibility, source reference, owner member id, schedule timestamps, and record timestamps.",
15617
- "Does not expose transcript upload, transcription finalize, consent grant, create, update, delete, transcript text, segment text, client secrets, unsafe metadata, raw provider payloads, credentials, tokens, or secrets by default."
15618
- ],
15619
- commands: ["list", "show"]
15620
- }
15621
- },
15622
15482
  "markdown-tree": {
15623
15483
  name: "markdown-tree",
15624
15484
  tier: "advanced",
@@ -15840,7 +15700,9 @@ async function resolveDoctorAuthOrganization(params) {
15840
15700
  if (!status || typeof status !== "object" || Array.isArray(status)) {
15841
15701
  return null;
15842
15702
  }
15843
- const organization = status.organization;
15703
+ const cliAuthStatus = status;
15704
+ if (cliAuthStatus.authenticated !== true) return null;
15705
+ const organization = cliAuthStatus.organization;
15844
15706
  if (!organization || typeof organization !== "object" || Array.isArray(organization)) {
15845
15707
  return null;
15846
15708
  }
@@ -15881,7 +15743,7 @@ async function runDoctor(cmd, opts) {
15881
15743
  name: "organization_id",
15882
15744
  ok: Boolean(organizationId || authOrganization?.id || authOrganization?.slug),
15883
15745
  status: organizationId || authOrganization?.id || authOrganization?.slug ? "resolved" : "missing",
15884
- source: organizationId ? "flag/stdin/env" : authOrganization ? "auth_token" : "unresolved",
15746
+ source: organizationId ? "explicit_flag" : authOrganization ? "auth_token" : "unresolved",
15885
15747
  ...authOrganization?.id ? { id: authOrganization.id } : {},
15886
15748
  ...authOrganization?.slug ? { slug: authOrganization.slug } : {}
15887
15749
  },
@@ -16134,20 +15996,20 @@ function attachDiscoveryHelp(program) {
16134
15996
  }
16135
15997
 
16136
15998
  // src/version.ts
16137
- var CLI_VERSION = "0.1.63";
15999
+ var CLI_VERSION = "0.1.66";
16138
16000
 
16139
16001
  // src/cli.ts
16140
16002
  function buildCli(options) {
16141
16003
  const program = new import_commander.Command();
16142
16004
  program.name("wave").description("Wave agent CLI").version(CLI_VERSION, "-V, --version", "output the version number").showHelpAfterError(false).allowExcessArguments(false).option("--token <token>", "API token (prefer WAVE_API_TOKEN env var)").option("--token-stdin", "Read API token from stdin").option(
16143
16005
  "--auth-json-stdin",
16144
- "Read auth/runtime context JSON from stdin (token, baseUrl, organizationId, ...)"
16006
+ "Read auth/runtime context JSON from stdin (token, baseUrl, tracing fields, ...)"
16145
16007
  ).option(
16146
16008
  "--base-url <baseUrl>",
16147
16009
  "API base URL (prefer WAVE_API_BASE_URL env var)"
16148
16010
  ).option(
16149
16011
  "--organization-id <organizationId>",
16150
- "Organization ID (prefer WAVE_ORGANIZATION_ID env var)"
16012
+ "Explicit organization ID override"
16151
16013
  ).option(
16152
16014
  "--config <configPath>",
16153
16015
  "Optional JSON config file (default: WAVE_CONFIG_PATH or ~/.wave/config.json when present)"
@@ -16210,7 +16072,6 @@ function buildCli(options) {
16210
16072
  registerMailCommands(program);
16211
16073
  registerPhantomCommands(program);
16212
16074
  registerDatasheetsCommands(program);
16213
- registerAiNotesCommands(program);
16214
16075
  registerAuthCommands(program);
16215
16076
  registerDiscoveryCommands(program);
16216
16077
  attachNamespaceDiscovery(program);
package/dist/index.js CHANGED
@@ -127,9 +127,7 @@ function getConfig(options) {
127
127
  const parsed = configSchema.safeParse({
128
128
  baseUrl,
129
129
  token,
130
- organizationId: toOptionalNonEmpty(
131
- options.organizationId ?? process.env.WAVE_ORGANIZATION_ID ?? process.env.WAVE_ORG_ID
132
- ),
130
+ organizationId: toOptionalNonEmpty(options.organizationId),
133
131
  timeoutMs: parseTimeoutMs(options.timeoutMs ?? process.env.WAVE_TIMEOUT_MS),
134
132
  debug: options.debug ?? parseDebug(process.env.WAVE_DEBUG),
135
133
  agentName: toOptionalNonEmpty(options.agentName ?? process.env.WAVE_AGENT_NAME),
@@ -2186,7 +2184,6 @@ function parseAuthJson(raw) {
2186
2184
  return {
2187
2185
  token: normalize3(obj.token),
2188
2186
  baseUrl: normalize3(obj.baseUrl ?? obj.base_url),
2189
- organizationId: normalize3(obj.organizationId ?? obj.organization_id),
2190
2187
  timeoutMs: typeof obj.timeoutMs === "number" || typeof obj.timeoutMs === "string" ? obj.timeoutMs : typeof obj.timeout_ms === "number" || typeof obj.timeout_ms === "string" ? obj.timeout_ms : void 0,
2191
2188
  debug: parseBool(obj.debug),
2192
2189
  agentName: normalize3(obj.agentName ?? obj.agent_name),
@@ -2269,7 +2266,6 @@ function resolveAuthToken(options, stdin, config, env) {
2269
2266
  { token: normalize3(options.token), source: "flag" },
2270
2267
  { token: normalize3(stdin.token), source: "stdin" },
2271
2268
  { token: normalize3(env.WAVE_API_TOKEN), source: "env" },
2272
- { token: normalize3(config.token), source: "config" },
2273
2269
  { token: normalize3(config.token), source: "config" }
2274
2270
  ];
2275
2271
  return candidates.find((candidate) => candidate.token) ?? { source: "none" };
@@ -2282,18 +2278,8 @@ function resolveFromSources(options, stdin, config, env) {
2282
2278
  normalize3(env.WAVE_API_URL),
2283
2279
  normalize3(config.baseUrl)
2284
2280
  );
2285
- const organizationCandidates = [
2286
- { organizationId: normalize3(options.organizationId), source: "flag" },
2287
- { organizationId: normalize3(stdin.organizationId), source: "stdin" },
2288
- { organizationId: normalize3(env.WAVE_ORGANIZATION_ID), source: "env" },
2289
- { organizationId: normalize3(env.WAVE_ORG_ID), source: "env" },
2290
- { organizationId: normalize3(config.organizationId), source: "config" }
2291
- ];
2292
- const resolvedOrganization = organizationCandidates.find((candidate) => candidate.organizationId) ?? {
2293
- organizationId: void 0,
2294
- source: "none"
2295
- };
2296
- const organizationId = resolvedOrganization.organizationId;
2281
+ const organizationId = normalize3(options.organizationId);
2282
+ const organizationIdSource = organizationId ? "flag" : "none";
2297
2283
  const timeoutMs = firstDefined(options.timeoutMs, stdin.timeoutMs, env.WAVE_TIMEOUT_MS, config.timeoutMs);
2298
2284
  const debug = firstDefined(
2299
2285
  options.debug,
@@ -2382,7 +2368,7 @@ function resolveFromSources(options, stdin, config, env) {
2382
2368
  const resolvedAuth = resolveAuthToken(options, stdin, config, env);
2383
2369
  return {
2384
2370
  organizationId,
2385
- organizationIdSource: resolvedOrganization.source,
2371
+ organizationIdSource,
2386
2372
  runtimeOptions: {
2387
2373
  token: resolvedAuth.token,
2388
2374
  tokenSource: resolvedAuth.token ? resolvedAuth.source : "none",
@@ -2522,7 +2508,9 @@ async function resolveCommandContext(options) {
2522
2508
  function organizationIdFromCliAuthStatus(data) {
2523
2509
  const status = data.cliAuthStatus;
2524
2510
  if (!status || typeof status !== "object" || Array.isArray(status)) return void 0;
2525
- const organization = status.organization;
2511
+ const cliAuthStatus = status;
2512
+ if (cliAuthStatus.authenticated !== true) return void 0;
2513
+ const organization = cliAuthStatus.organization;
2526
2514
  if (!organization || typeof organization !== "object" || Array.isArray(organization)) return void 0;
2527
2515
  return normalize3(organization.id);
2528
2516
  }
@@ -14459,7 +14447,7 @@ async function runDatasheetsQuery(cmd, config) {
14459
14447
  });
14460
14448
  }
14461
14449
  async function runDatasheetsMutation(cmd, opts, config) {
14462
- const context = await resolveCommandContext(cmd.optsWithGlobals());
14450
+ const context = config.organizationContext === "optional" ? await resolveUnscopedCommandContext(cmd.optsWithGlobals()) : await resolveCommandContext(cmd.optsWithGlobals());
14463
14451
  const variables = config.organizationContext === "optional" ? context.organizationId ? { organization_id: context.organizationId } : {} : { organization_id: resolveOrganizationId(context.organizationId) };
14464
14452
  for (const id of config.requiredIds ?? []) {
14465
14453
  variables[id.variable] = requireNonEmpty(opts[id.option], id.label, config.command);
@@ -14496,7 +14484,7 @@ async function runDatasheetsMutation(cmd, opts, config) {
14496
14484
  runtimeOptions: context.runtimeOptions,
14497
14485
  field: config.field,
14498
14486
  variables: normalizeGraphqlVariables2(variables),
14499
- variableTypes: { organization_id: "ID!" },
14487
+ variableTypes: config.organizationContext === "optional" && !context.organizationId ? {} : { organization_id: "ID!" },
14500
14488
  selectionSet: DATASHEET_MUTATION_SELECTION
14501
14489
  });
14502
14490
  }
@@ -14788,115 +14776,6 @@ function registerDatasheetsCommands(program) {
14788
14776
  });
14789
14777
  }
14790
14778
 
14791
- // src/commands/aiNotes.ts
14792
- var AI_NOTE_SAFE_FIELDS = [
14793
- "id",
14794
- "slug",
14795
- "title",
14796
- "status",
14797
- "visibility",
14798
- "sourceType",
14799
- "sourceReference",
14800
- "ownerMemberId",
14801
- "scheduledStartAt",
14802
- "scheduledEndAt",
14803
- "createdAt",
14804
- "updatedAt"
14805
- ];
14806
- var AI_NOTE_SELECTION = `{ ${AI_NOTE_SAFE_FIELDS.join(" ")} }`;
14807
- var AI_NOTES_SELECTION = AI_NOTE_SELECTION;
14808
- function pickSafeAiNoteFields(value) {
14809
- if (!value || typeof value !== "object" || Array.isArray(value)) {
14810
- return null;
14811
- }
14812
- const record = value;
14813
- const safe = {};
14814
- for (const field of AI_NOTE_SAFE_FIELDS) {
14815
- if (Object.prototype.hasOwnProperty.call(record, field)) {
14816
- safe[field] = record[field];
14817
- }
14818
- }
14819
- return safe;
14820
- }
14821
- function projectAiNotesPayload(payload) {
14822
- if (Array.isArray(payload)) {
14823
- return payload.map((item) => pickSafeAiNoteFields(item)).filter(Boolean);
14824
- }
14825
- if (!payload || typeof payload !== "object") {
14826
- return payload;
14827
- }
14828
- return pickSafeAiNoteFields(payload);
14829
- }
14830
- function showVariables(opts) {
14831
- const id = typeof opts.id === "string" && opts.id.trim() !== "" ? opts.id.trim() : void 0;
14832
- const slug = typeof opts.slug === "string" && opts.slug.trim() !== "" ? opts.slug.trim() : void 0;
14833
- if (!id && !slug || id && slug) {
14834
- throw new CliError({
14835
- message: "Provide exactly one AI Note identifier: --id or --slug.",
14836
- kind: "invalid_args",
14837
- status: 400,
14838
- exitCode: EXIT_CODES.invalidArgs,
14839
- details: { requiredOneOf: ["--id", "--slug"] }
14840
- });
14841
- }
14842
- return id ? { id } : { slug };
14843
- }
14844
- async function runAiNotesQuery(cmd, config) {
14845
- const context = await resolveCommandContext(cmd.optsWithGlobals());
14846
- await runGraphqlQueryCommand({
14847
- command: config.command,
14848
- operationName: config.operationName,
14849
- runtimeOptions: context.runtimeOptions,
14850
- field: config.field,
14851
- variables: normalizeGraphqlVariables2({
14852
- organization_id: resolveOrganizationId(context.organizationId),
14853
- ...config.variables
14854
- }),
14855
- variableTypes: config.variableTypes,
14856
- selectionSet: config.selectionSet,
14857
- isList: config.isList,
14858
- isShow: config.isShow,
14859
- transformData: projectAiNotesPayload
14860
- });
14861
- }
14862
- function registerAiNotesCommands(program) {
14863
- const aiNotes = program.command("ai-notes").description("AI Notes read-only list and detail metadata");
14864
- aiNotes.command("list").description("Read safe AI Note metadata without transcripts or provider payloads").option("--page <page>").option("--per <per>").action(async (opts, cmd) => {
14865
- await runAiNotesQuery(cmd, {
14866
- command: "ai-notes.list",
14867
- operationName: "AiNotes",
14868
- field: "ai_notes",
14869
- variables: {
14870
- page: opts.page,
14871
- per: opts.per
14872
- },
14873
- variableTypes: {
14874
- organization_id: "ID!",
14875
- page: "Int",
14876
- per: "Int"
14877
- },
14878
- selectionSet: AI_NOTES_SELECTION,
14879
- isList: true
14880
- });
14881
- });
14882
- aiNotes.command("show").description("Read safe AI Note detail metadata by id or slug").option("--id <id>").option("--slug <slug>").action(async (opts, cmd) => {
14883
- const variables = showVariables(opts);
14884
- await runAiNotesQuery(cmd, {
14885
- command: "ai-notes.show",
14886
- operationName: "AiNote",
14887
- field: "ai_note",
14888
- variables,
14889
- variableTypes: {
14890
- organization_id: "ID!",
14891
- ...variables.id ? { id: "ID!" } : {},
14892
- ...variables.slug ? { slug: "String!" } : {}
14893
- },
14894
- selectionSet: AI_NOTE_SELECTION,
14895
- isShow: true
14896
- });
14897
- });
14898
- }
14899
-
14900
14779
  // src/commands/atlasAuthoring.ts
14901
14780
  import { z as z19 } from "zod";
14902
14781
  var idSchema14 = z19.string().trim().min(1);
@@ -15071,7 +14950,7 @@ function registerAtlasAuthoringCommands(program) {
15071
14950
  });
15072
14951
  });
15073
14952
  const automations = program.command("automations").description("Bounded Automation authoring operations");
15074
- 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) => {
14953
+ 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("--agent-id <agentId>", "Optional executor Agent id for a repeat Automation").option("--status <status>").option("--priority <priority>").option("--due-date <date>", "ISO-8601 date (YYYY-MM-DD)").action(async (opts, cmd) => {
15075
14954
  const idempotencyKey = idempotencyKeySchema.parse(opts.idempotencyKey);
15076
14955
  const context = await resolveCommandContext(cmd.optsWithGlobals());
15077
14956
  const organizationId = resolveOrganizationId(context.organizationId);
@@ -15093,6 +14972,7 @@ function registerAtlasAuthoringCommands(program) {
15093
14972
  ...opts.description !== void 0 ? { description: String(opts.description) } : {},
15094
14973
  ...opts.notes !== void 0 ? { notes: String(opts.notes) } : {},
15095
14974
  ...opts.memberId !== void 0 ? { member_id: idSchema14.parse(opts.memberId) } : {},
14975
+ ...opts.agentId !== void 0 ? { agentId: idSchema14.parse(opts.agentId) } : {},
15096
14976
  ...opts.status !== void 0 ? { status: String(opts.status) } : {},
15097
14977
  ...opts.priority !== void 0 ? { priority: String(opts.priority) } : {},
15098
14978
  ...opts.dueDate !== void 0 ? { due_date: isoDateSchema.parse(opts.dueDate) } : {}
@@ -15163,7 +15043,6 @@ var PRIMARY_NAMESPACES = [
15163
15043
  "planner",
15164
15044
  "mail",
15165
15045
  "datasheets",
15166
- "ai-notes",
15167
15046
  "phantom",
15168
15047
  "tasks",
15169
15048
  "projects",
@@ -15328,7 +15207,7 @@ var NAMESPACE_DOCS = {
15328
15207
  tier: "primary",
15329
15208
  description: "Bounded Automation create and persisted readback operations.",
15330
15209
  examples: [
15331
- `wave automations create --summary "Weekly review" --ai-task-config '{"prompt":"Review tasks"}' --idempotency-key automation-create-001`,
15210
+ `wave automations create --summary "Weekly review" --agent-id 123 --ai-task-config '{"cycle":"repeat","repeatSchedule":{"interval":1,"frequency":"week","weekdays":[1,3],"at":"2:30 PM","starting":"2026-07-20T00:00:00.000Z","ending":"never","endingRuns":1,"endingDate":null,"timezone":"America/Phoenix"}}' --idempotency-key automation-create-001`,
15332
15211
  "wave automations show --id 123"
15333
15212
  ],
15334
15213
  schema: {
@@ -15337,6 +15216,7 @@ var NAMESPACE_DOCS = {
15337
15216
  safety: [
15338
15217
  "Create calls only createAutomation with an explicit idempotency key.",
15339
15218
  "Only the API-defined ai_task_config field accepts validated JSON.",
15219
+ "Optional executor Agent linkage is sent only through the API-defined top-level agentId input.",
15340
15220
  "Does not create a project Task, run an Automation, or invoke AI OS actions.",
15341
15221
  "Show uses the API-owned automation query by id; no slug fallback is implemented."
15342
15222
  ],
@@ -15598,26 +15478,6 @@ var NAMESPACE_DOCS = {
15598
15478
  ]
15599
15479
  }
15600
15480
  },
15601
- "ai-notes": {
15602
- name: "ai-notes",
15603
- tier: "primary",
15604
- description: "AI Notes read-only list and detail metadata for CLI-backed Atlas and harness inspection.",
15605
- examples: [
15606
- "wave ai-notes list --page 1 --per 20",
15607
- "wave ai-notes show --id note_123",
15608
- "wave ai-notes show --slug weekly-summary"
15609
- ],
15610
- schema: {
15611
- output: "json-envelope-default",
15612
- readOnly: true,
15613
- safety: [
15614
- "Uses API-owned GraphQL read fields aiNotes and aiNote.",
15615
- "List/show output is limited to safe AI Note identifiers, title, status, visibility, source reference, owner member id, schedule timestamps, and record timestamps.",
15616
- "Does not expose transcript upload, transcription finalize, consent grant, create, update, delete, transcript text, segment text, client secrets, unsafe metadata, raw provider payloads, credentials, tokens, or secrets by default."
15617
- ],
15618
- commands: ["list", "show"]
15619
- }
15620
- },
15621
15481
  "markdown-tree": {
15622
15482
  name: "markdown-tree",
15623
15483
  tier: "advanced",
@@ -15839,7 +15699,9 @@ async function resolveDoctorAuthOrganization(params) {
15839
15699
  if (!status || typeof status !== "object" || Array.isArray(status)) {
15840
15700
  return null;
15841
15701
  }
15842
- const organization = status.organization;
15702
+ const cliAuthStatus = status;
15703
+ if (cliAuthStatus.authenticated !== true) return null;
15704
+ const organization = cliAuthStatus.organization;
15843
15705
  if (!organization || typeof organization !== "object" || Array.isArray(organization)) {
15844
15706
  return null;
15845
15707
  }
@@ -15880,7 +15742,7 @@ async function runDoctor(cmd, opts) {
15880
15742
  name: "organization_id",
15881
15743
  ok: Boolean(organizationId || authOrganization?.id || authOrganization?.slug),
15882
15744
  status: organizationId || authOrganization?.id || authOrganization?.slug ? "resolved" : "missing",
15883
- source: organizationId ? "flag/stdin/env" : authOrganization ? "auth_token" : "unresolved",
15745
+ source: organizationId ? "explicit_flag" : authOrganization ? "auth_token" : "unresolved",
15884
15746
  ...authOrganization?.id ? { id: authOrganization.id } : {},
15885
15747
  ...authOrganization?.slug ? { slug: authOrganization.slug } : {}
15886
15748
  },
@@ -16133,20 +15995,20 @@ function attachDiscoveryHelp(program) {
16133
15995
  }
16134
15996
 
16135
15997
  // src/version.ts
16136
- var CLI_VERSION = "0.1.63";
15998
+ var CLI_VERSION = "0.1.66";
16137
15999
 
16138
16000
  // src/cli.ts
16139
16001
  function buildCli(options) {
16140
16002
  const program = new Command();
16141
16003
  program.name("wave").description("Wave agent CLI").version(CLI_VERSION, "-V, --version", "output the version number").showHelpAfterError(false).allowExcessArguments(false).option("--token <token>", "API token (prefer WAVE_API_TOKEN env var)").option("--token-stdin", "Read API token from stdin").option(
16142
16004
  "--auth-json-stdin",
16143
- "Read auth/runtime context JSON from stdin (token, baseUrl, organizationId, ...)"
16005
+ "Read auth/runtime context JSON from stdin (token, baseUrl, tracing fields, ...)"
16144
16006
  ).option(
16145
16007
  "--base-url <baseUrl>",
16146
16008
  "API base URL (prefer WAVE_API_BASE_URL env var)"
16147
16009
  ).option(
16148
16010
  "--organization-id <organizationId>",
16149
- "Organization ID (prefer WAVE_ORGANIZATION_ID env var)"
16011
+ "Explicit organization ID override"
16150
16012
  ).option(
16151
16013
  "--config <configPath>",
16152
16014
  "Optional JSON config file (default: WAVE_CONFIG_PATH or ~/.wave/config.json when present)"
@@ -16209,7 +16071,6 @@ function buildCli(options) {
16209
16071
  registerMailCommands(program);
16210
16072
  registerPhantomCommands(program);
16211
16073
  registerDatasheetsCommands(program);
16212
- registerAiNotesCommands(program);
16213
16074
  registerAuthCommands(program);
16214
16075
  registerDiscoveryCommands(program);
16215
16076
  attachNamespaceDiscovery(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wave-ai-os/wave-cli",
3
- "version": "0.1.63",
3
+ "version": "0.1.66",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "wave": "dist/index.js"
@@ -2,6 +2,7 @@
2
2
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { spawnSync } from "node:child_process";
5
+ import { REQUIRED_WAVE_RUNTIME_INPUTS } from "./cli-token-scope.mjs";
5
6
 
6
7
  const DEFAULTS = {
7
8
  runs: 10,
@@ -479,7 +480,7 @@ function main() {
479
480
  };
480
481
 
481
482
  const waveEntryAbs = resolve(cwd, options.waveEntry);
482
- const waveMissing = ["WAVE_API_BASE_URL", "WAVE_API_TOKEN", "WAVE_ORGANIZATION_ID"].filter((key) => !baseEnv[key]);
483
+ const waveMissing = REQUIRED_WAVE_RUNTIME_INPUTS.filter((key) => !baseEnv[key]);
483
484
  const waveReady = existsSync(waveEntryAbs) && waveMissing.length === 0;
484
485
 
485
486
  const obsidian = resolveObsidianBinary(options.obsidianBin);
@@ -0,0 +1,10 @@
1
+ export const REQUIRED_WAVE_RUNTIME_INPUTS = ["WAVE_API_BASE_URL", "WAVE_API_TOKEN"];
2
+
3
+ export function organizationIdFromAuthenticatedStatus(envelope) {
4
+ if (!envelope || envelope.ok !== true) return undefined;
5
+ if (envelope.data?.authenticated !== true) return undefined;
6
+ const organizationId = envelope.data?.organization?.id;
7
+ return typeof organizationId === "string" && organizationId.trim() !== ""
8
+ ? organizationId
9
+ : undefined;
10
+ }
@@ -2,6 +2,7 @@
2
2
  import { readFileSync } from "node:fs";
3
3
  import { spawnSync } from "node:child_process";
4
4
  import { resolve } from "node:path";
5
+ import { organizationIdFromAuthenticatedStatus } from "./cli-token-scope.mjs";
5
6
 
6
7
  function loadDotEnv(filePath) {
7
8
  const raw = readFileSync(filePath, "utf8");
@@ -348,12 +349,18 @@ const dot = loadDotEnv(envFile);
348
349
  const env = {
349
350
  WAVE_API_BASE_URL: dot.WAVE_API_BASE_URL,
350
351
  WAVE_API_TOKEN: dot.WAVE_API_TOKEN,
351
- WAVE_ORGANIZATION_ID: dot.WAVE_ORGANIZATION_ID,
352
352
  WAVE_AGENT_NAME: dot.WAVE_AGENT_NAME || "cli-verifier",
353
353
  WAVE_AGENT_RUN_ID: `verify-${Date.now()}`,
354
354
  WAVE_TIMEOUT_MS: dot.WAVE_TIMEOUT_MS || "10000"
355
355
  };
356
356
 
357
+ const authStatus = runWave(["auth", "status"], env);
358
+ const orgId = organizationIdFromAuthenticatedStatus(authStatus.parsed);
359
+ if (!orgId) {
360
+ console.error("verify-dev-api failed: authenticated CLI token status did not return an organization id.");
361
+ process.exit(1);
362
+ }
363
+
357
364
  const idLookup = {};
358
365
  const listSeeds = [
359
366
  ["projects", ["projects", "list", "--page", "1", "--per", "2"]],
@@ -386,7 +393,7 @@ const listSeeds = [
386
393
  ["quarterlyObjectives", ["foundation", "quarterly-objectives", "list", "--page", "1", "--per", "2"]]
387
394
  ];
388
395
 
389
- const results = [];
396
+ const results = [authStatus];
390
397
  for (const [key, args] of listSeeds) {
391
398
  const res = runWave(args, env);
392
399
  results.push(res);
@@ -413,7 +420,6 @@ for (const [key, args] of listSeeds) {
413
420
  }
414
421
  }
415
422
 
416
- const orgId = env.WAVE_ORGANIZATION_ID;
417
423
  const projectId = idLookup.projects;
418
424
  const taskId = idLookup.tasks;
419
425
  const rockId = idLookup.rocks;