@ted-galago/wave-cli 0.1.16 → 0.1.18

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.js CHANGED
@@ -180,6 +180,22 @@ function graphqlOperationName(command) {
180
180
  function toCamelCase(value) {
181
181
  return value.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
182
182
  }
183
+ function capitalizeFirst(value) {
184
+ return value.length === 0 ? value : value[0].toUpperCase() + value.slice(1);
185
+ }
186
+ var MUTATION_PARAMS_INPUT_TYPE_OVERRIDES = {
187
+ createOpenAiRealtimeClientSecret: "OpenAiRealtimeClientSecretInput",
188
+ createOpenAiRealtimeSession: "OpenAiRealtimeSessionInput",
189
+ createOpenAiTranscription: "OpenAiTranscriptionInput",
190
+ finalizeOpenAiTranscription: "OpenAiFinalizeTranscriptionInput"
191
+ };
192
+ function inferMutationParamsInputType(input) {
193
+ if (input.operationType !== "mutation") {
194
+ return null;
195
+ }
196
+ const graphqlField = toCamelCase(input.field);
197
+ return MUTATION_PARAMS_INPUT_TYPE_OVERRIDES[graphqlField] ?? `${capitalizeFirst(graphqlField)}ParamsInput`;
198
+ }
183
199
  function inferStatusFromGraphqlErrors(errors) {
184
200
  if (!Array.isArray(errors) || errors.length === 0) {
185
201
  return 400;
@@ -412,7 +428,7 @@ function buildFeedbackFindRequestBody(command, identity) {
412
428
  page: 1,
413
429
  per: 1
414
430
  },
415
- selectionSet: "{ data { id type attributes } count currentPage totalPages }"
431
+ selectionSet: "{ data { id type attributes { id name slug year quarter organizationId memberIds } } count currentPage totalPages }"
416
432
  });
417
433
  }
418
434
  async function requestGraphqlHttp(params) {
@@ -483,7 +499,13 @@ function graphqlTypeForValue(value) {
483
499
  }
484
500
  return "JSON";
485
501
  }
486
- function graphqlTypeForVariable(name, value) {
502
+ function graphqlTypeForVariable(input, name, value) {
503
+ if (name === "params") {
504
+ const paramsInputType = inferMutationParamsInputType(input);
505
+ if (paramsInputType) {
506
+ return paramsInputType;
507
+ }
508
+ }
487
509
  if (name === "id" || name.endsWith("Id")) {
488
510
  return "ID";
489
511
  }
@@ -527,7 +549,7 @@ function buildGraphqlBody(input) {
527
549
  const variableDecl = variableEntries.map(([name, value]) => {
528
550
  const overriddenType = graphqlVariableTypes[name];
529
551
  const hasOverriddenType = typeof overriddenType === "string" && overriddenType.trim().length > 0;
530
- const typeName = hasOverriddenType ? overriddenType.trim() : graphqlTypeForVariable(name, value);
552
+ const typeName = hasOverriddenType ? overriddenType.trim() : graphqlTypeForVariable(input, name, value);
531
553
  return `$${name}: ${hasOverriddenType ? typeName : withNonNull(typeName)}`;
532
554
  }).join(", ");
533
555
  const fieldArgs = variableEntries.map(([name]) => `${name}: $${name}`).join(", ");
@@ -822,8 +844,7 @@ var RESOURCE_QUERY_FIELDS = {
822
844
  "memberIds",
823
845
  "leadMemberId",
824
846
  "organizationId",
825
- "responsibilities",
826
- "keyMetric"
847
+ "responsibilities"
827
848
  ],
828
849
  member: [
829
850
  "slug",
@@ -1279,16 +1300,16 @@ function defaultQuerySelectionSet(field, isList) {
1279
1300
  const canonicalField = RESOURCE_FIELD_ALIASES[field] ?? field;
1280
1301
  const explicitFields = RESOURCE_QUERY_FIELDS[canonicalField];
1281
1302
  if (explicitFields) {
1303
+ const attributes = explicitFields.length > 0 ? `attributes { ${Array.from(/* @__PURE__ */ new Set(["id", ...explicitFields])).join(" ")} }` : "attributes";
1282
1304
  if (isList) {
1283
- return "{ data { id type attributes } count currentPage totalPages }";
1305
+ return `{ data { id type ${attributes} } count currentPage totalPages }`;
1284
1306
  }
1285
- const fields = Array.from(/* @__PURE__ */ new Set(["id", "type", ...explicitFields, "attributes"])).join(" ");
1286
- return `{ ${fields} }`;
1307
+ return `{ id type ${attributes} }`;
1287
1308
  }
1288
1309
  if (isList) {
1289
- return "{ data { id type attributes } count currentPage totalPages }";
1310
+ return "{ data { id type } count currentPage totalPages }";
1290
1311
  }
1291
- return "{ id type attributes }";
1312
+ return "{ id type }";
1292
1313
  }
1293
1314
  function isRecord(value) {
1294
1315
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -2593,7 +2614,10 @@ var idSchema3 = z4.string().min(1);
2593
2614
  var projectCreateDataJsonHelp = buildDataJsonHelp("project", "create") ?? 'JSON object for project or {"project": {...}}';
2594
2615
  var projectUpdateDataJsonHelp = buildDataJsonHelp("project", "update") ?? 'JSON object for project or {"project": {...}}';
2595
2616
  var projectsIndexMinimalSelectionSet = "{ count currentPage totalPages data { id type attributes { name slug status priority } } }";
2596
- var projectShowFullSelectionSet = "{ id type name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type attributes viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type attributes filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull } replies { id type value memberId createdAt updatedAt commentType commentableId commentableType parentCommentId emojis { id name memberId } resources { ...ResourceSummaryFull } replies { id type } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }";
2617
+ var displayPreferenceAttributesSelectionSet = "attributes { id viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId }";
2618
+ var filterPreferenceAttributesSelectionSet = "attributes { id filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId }";
2619
+ var healthUpdateSummarySelectionSet = "id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull }";
2620
+ var projectShowFullSelectionSet = `{ id type name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type ${displayPreferenceAttributesSelectionSet} viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type ${filterPreferenceAttributesSelectionSet} filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { ${healthUpdateSummarySelectionSet} replies { ${healthUpdateSummarySelectionSet} replies { id type } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }`;
2597
2621
  function asRecord2(value) {
2598
2622
  return value && typeof value === "object" ? value : null;
2599
2623
  }
@@ -3998,7 +4022,7 @@ function registerSystemToolCommands(program) {
3998
4022
  page: 1,
3999
4023
  per: 200
4000
4024
  },
4001
- selectionSet: "{ data { id type slug summary description memberId status rank createdAt updatedAt headlineType teamIds meetingId labelIds attributes } count currentPage totalPages }",
4025
+ selectionSet: "{ data { id type slug summary description memberId status rank createdAt updatedAt headlineType teamIds meetingId labelIds attributes { id slug summary description memberId status rank createdAt updatedAt headlineType teamIds meetingId labelIds } } count currentPage totalPages }",
4002
4026
  transformData: (value) => {
4003
4027
  if (!value || typeof value !== "object") {
4004
4028
  return null;
@@ -4615,7 +4639,13 @@ function registerFoundationCommands(program) {
4615
4639
  import { z as z12 } from "zod";
4616
4640
  var idSchema11 = z12.string().min(1);
4617
4641
  var jsonObjectSchema = z12.record(z12.string(), z12.unknown());
4618
- var childListMinimalSelectionSet = "{ data { id type attributes } count currentPage totalPages }";
4642
+ function buildChildListSelectionSet(parentField, extraFields = []) {
4643
+ const fields = Array.from(
4644
+ /* @__PURE__ */ new Set(["id", "type", "name", "status", "priority", "rank", "dueDate", "memberId", parentField, ...extraFields])
4645
+ );
4646
+ const attributeFields = fields.filter((field) => field !== "type");
4647
+ return `{ data { ${fields.join(" ")} attributes { ${attributeFields.join(" ")} } } count currentPage totalPages }`;
4648
+ }
4619
4649
  function parseJsonObject2(raw) {
4620
4650
  try {
4621
4651
  const parsed = JSON.parse(raw);
@@ -4820,7 +4850,7 @@ function registerChildEntityCommands(program) {
4820
4850
  createOperationName: "SubtasksCreate",
4821
4851
  updateOperationName: "SubtasksUpdate",
4822
4852
  destroyOperationName: "SubtasksDestroy",
4823
- listSelectionSet: childListMinimalSelectionSet,
4853
+ listSelectionSet: buildChildListSelectionSet("taskId"),
4824
4854
  listParentTypedField: "taskId",
4825
4855
  normalizeCreateBody: normalizeSubtaskCreateBody
4826
4856
  });
@@ -4839,7 +4869,7 @@ function registerChildEntityCommands(program) {
4839
4869
  createOperationName: "MilestonesCreate",
4840
4870
  updateOperationName: "MilestonesUpdate",
4841
4871
  destroyOperationName: "MilestonesDestroy",
4842
- listSelectionSet: childListMinimalSelectionSet
4872
+ listSelectionSet: buildChildListSelectionSet("rockId")
4843
4873
  });
4844
4874
  registerChildCommands(program, {
4845
4875
  command: "subitems",
@@ -4856,7 +4886,7 @@ function registerChildEntityCommands(program) {
4856
4886
  createOperationName: "SubitemsCreate",
4857
4887
  updateOperationName: "SubitemsUpdate",
4858
4888
  destroyOperationName: "SubitemsDestroy",
4859
- listSelectionSet: childListMinimalSelectionSet,
4889
+ listSelectionSet: buildChildListSelectionSet("listItemId"),
4860
4890
  listParentTypedField: "listItemId"
4861
4891
  });
4862
4892
  registerChildCommands(program, {
@@ -4874,7 +4904,7 @@ function registerChildEntityCommands(program) {
4874
4904
  createOperationName: "SubtodosCreate",
4875
4905
  updateOperationName: "SubtodosUpdate",
4876
4906
  destroyOperationName: "SubtodosDestroy",
4877
- listSelectionSet: childListMinimalSelectionSet,
4907
+ listSelectionSet: buildChildListSelectionSet("todoId"),
4878
4908
  listParentTypedField: "todoId"
4879
4909
  });
4880
4910
  registerChildCommands(program, {
@@ -4892,7 +4922,7 @@ function registerChildEntityCommands(program) {
4892
4922
  createOperationName: "SubissuesCreate",
4893
4923
  updateOperationName: "SubissuesUpdate",
4894
4924
  destroyOperationName: "SubissuesDestroy",
4895
- listSelectionSet: childListMinimalSelectionSet,
4925
+ listSelectionSet: buildChildListSelectionSet("issueId"),
4896
4926
  listParentTypedField: "issueId"
4897
4927
  });
4898
4928
  registerChildCommands(program, {
@@ -4910,7 +4940,7 @@ function registerChildEntityCommands(program) {
4910
4940
  createOperationName: "TalkingPointsCreate",
4911
4941
  updateOperationName: "TalkingPointsUpdate",
4912
4942
  destroyOperationName: "TalkingPointsDestroy",
4913
- listSelectionSet: childListMinimalSelectionSet,
4943
+ listSelectionSet: buildChildListSelectionSet("meetingId", ["description", "creatorId", "slug"]),
4914
4944
  listParentTypedField: "meetingId"
4915
4945
  });
4916
4946
  }
@@ -4919,6 +4949,7 @@ function registerChildEntityCommands(program) {
4919
4949
  import { z as z13 } from "zod";
4920
4950
  var idSchema12 = z13.string().min(1);
4921
4951
  var nonEmptyString = z13.string().min(1);
4952
+ var contentAttributesSelection = "attributes { id type name slug content firstChildSlug rootParentSlug status contentType lastEdited organizationId memberId focusMemberId focusTeamId teamId creatorId createdAt updatedAt childCount assignmentType contentableId contentableSlug contentableType votesTotal labelIds rootContentId parentContentId }";
4922
4953
  function assertUpdateFields(params) {
4923
4954
  if (!params.name && !params.content && !params.status) {
4924
4955
  throw new CliError({
@@ -4966,7 +4997,7 @@ function registerContentCommands(program) {
4966
4997
  per: opts.per
4967
4998
  }),
4968
4999
  isList: true,
4969
- selectionSet: "{ count currentPage totalPages data { id type attributes } }"
5000
+ selectionSet: `{ count currentPage totalPages data { id type ${contentAttributesSelection} } }`
4970
5001
  });
4971
5002
  });
4972
5003
  content.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
@@ -4983,7 +5014,7 @@ function registerContentCommands(program) {
4983
5014
  id
4984
5015
  }),
4985
5016
  isShow: true,
4986
- selectionSet: "{ id type name slug firstChildSlug rootParentSlug status contentType lastEdited organizationId memberId focusMemberId focusTeamId teamId creatorId createdAt updatedAt childCount assignmentType contentableId contentableSlug contentableType votesTotal labelIds rootContentId parentContentId attributes }"
5017
+ selectionSet: `{ id type resources { id resourceType slug url } ${contentAttributesSelection} }`
4987
5018
  });
4988
5019
  });
4989
5020
  content.command("update").requiredOption("--id <id>").option("--name <name>").option("--body <body>").option("--status <status>").action(async (opts, cmd) => {
@@ -6087,7 +6118,7 @@ function registerMutationCapabilityCommands(program) {
6087
6118
  import { readFile } from "fs/promises";
6088
6119
  import { z as z16 } from "zod";
6089
6120
  var sourceSchema = z16.enum(["canonical_osmd", "agent_overlay", "agent_wiki"]);
6090
- var accessSchema = z16.enum(["read_only", "read_write", "append_only"]);
6121
+ var accessSchema = z16.enum(["read_only", "read_write", "append_only"]).catch("read_write");
6091
6122
  var ownerSchema = z16.enum(["system", "atlas"]);
6092
6123
  var suggestedActionSchema = z16.enum([
6093
6124
  "read",
@@ -6097,7 +6128,7 @@ var suggestedActionSchema = z16.enum([
6097
6128
  "append",
6098
6129
  "forbidden",
6099
6130
  "invalid_parent"
6100
- ]);
6131
+ ]).catch("update");
6101
6132
  var agentMarkdownErrorCodeSchema = z16.enum([
6102
6133
  "canonical_osmd_read_only",
6103
6134
  "agent_parent_not_found",
@@ -6108,9 +6139,13 @@ var agentMarkdownErrorCodeSchema = z16.enum([
6108
6139
  "unsupported_agent_file",
6109
6140
  "invalid_agent_wiki_path"
6110
6141
  ]);
6142
+ var agentMarkdownErrorCodeFieldSchema = agentMarkdownErrorCodeSchema.nullable().catch(null);
6111
6143
  var nonEmptyString3 = z16.string().min(1);
6112
6144
  var nonNegativeInt3 = z16.coerce.number().int().min(0);
6113
- var agentOverlayFileSchema = z16.enum(["notes.md", "log.md"]);
6145
+ var supportedAgentOverlayFile = "notes.md";
6146
+ var supportedWikiIndexFile = "index.md";
6147
+ var supportedWikiLogFile = "log.md";
6148
+ var agentOverlayFileSchema = z16.enum([supportedAgentOverlayFile]);
6114
6149
  var agentMarkdownFileSchema = z16.object({
6115
6150
  path: z16.string(),
6116
6151
  source: sourceSchema,
@@ -6123,7 +6158,7 @@ var agentMarkdownFileSchema = z16.object({
6123
6158
  parentRef: z16.string().nullable().optional(),
6124
6159
  agentChildrenAllowed: z16.boolean(),
6125
6160
  suggestedAction: suggestedActionSchema,
6126
- errorCode: agentMarkdownErrorCodeSchema.nullable().optional(),
6161
+ errorCode: agentMarkdownErrorCodeFieldSchema.optional(),
6127
6162
  content: z16.string().nullable().optional(),
6128
6163
  url: z16.string().nullable().optional()
6129
6164
  }).transform((value) => ({
@@ -6197,6 +6232,21 @@ var AGENT_JSON_KEY_ALIASES = {
6197
6232
  suggested_action: "suggestedAction",
6198
6233
  error_code: "errorCode"
6199
6234
  };
6235
+ function isSupportedAgentMarkdownFile(file) {
6236
+ if (file.source !== "agent_overlay") {
6237
+ return true;
6238
+ }
6239
+ return file.path === `.agent/${supportedAgentOverlayFile}` || file.path.endsWith(`/.agent/${supportedAgentOverlayFile}`);
6240
+ }
6241
+ function filterSupportedAgentMarkdownData(data) {
6242
+ if (isRecord5(data) && Array.isArray(data.files)) {
6243
+ return {
6244
+ ...data,
6245
+ files: data.files.filter(isSupportedAgentMarkdownFile)
6246
+ };
6247
+ }
6248
+ return data;
6249
+ }
6200
6250
  var contentStdinPromise = null;
6201
6251
  function isRecord5(value) {
6202
6252
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -6369,7 +6419,7 @@ async function runAgentMarkdownMutation(params) {
6369
6419
  envelope: buildSuccessEnvelope({
6370
6420
  command: params.command,
6371
6421
  status: mutationPayload.status,
6372
- data: parsedData.data,
6422
+ data: filterSupportedAgentMarkdownData(parsedData.data),
6373
6423
  requestId: result.envelope.meta.requestId
6374
6424
  })
6375
6425
  });
@@ -6380,24 +6430,50 @@ function normalizeAgentFilePath(file) {
6380
6430
  const parsed = agentOverlayFileSchema.safeParse(fileName);
6381
6431
  if (!parsed.success) {
6382
6432
  throw new CliError({
6383
- message: ".agent supports only notes.md and log.md in this CLI slice.",
6433
+ message: ".agent supports only notes.md in this CLI slice.",
6384
6434
  kind: "invalid_args",
6385
6435
  status: 400,
6386
6436
  exitCode: EXIT_CODES.invalidArgs,
6387
- details: { supportedFiles: ["notes.md", "log.md"] }
6437
+ details: { supportedFiles: [supportedAgentOverlayFile] }
6388
6438
  });
6389
6439
  }
6390
6440
  return `.agent/${parsed.data}`;
6391
6441
  }
6392
- function normalizeWikiPath(path) {
6442
+ function supportedWikiFilesMessage(files) {
6443
+ return `Agent Wiki file commands support only ${files.join(" and ")} in this CLI slice.`;
6444
+ }
6445
+ function normalizeWikiPath(path, options = {}) {
6446
+ const supportedFiles = options.supportedFiles ?? [supportedWikiIndexFile, supportedWikiLogFile];
6393
6447
  const trimmed = nonEmptyString3.parse(path).trim().replace(/^\/+/, "");
6394
6448
  if (trimmed.localeCompare("Agent Wiki", void 0, { sensitivity: "accent" }) === 0) {
6395
- return "Agent Wiki";
6449
+ if (options.allowRoot) {
6450
+ return "Agent Wiki";
6451
+ }
6452
+ throw new CliError({
6453
+ message: supportedWikiFilesMessage(supportedFiles),
6454
+ kind: "invalid_args",
6455
+ status: 400,
6456
+ exitCode: EXIT_CODES.invalidArgs,
6457
+ details: { supportedFiles }
6458
+ });
6396
6459
  }
6397
- if (trimmed.toLowerCase().startsWith("agent wiki/")) {
6398
- return `Agent Wiki/${trimmed.slice("Agent Wiki/".length)}`;
6460
+ const fileName = trimmed.toLowerCase().startsWith("agent wiki/") ? trimmed.slice("Agent Wiki/".length) : trimmed;
6461
+ if (!supportedFiles.includes(fileName)) {
6462
+ throw new CliError({
6463
+ message: supportedWikiFilesMessage(supportedFiles),
6464
+ kind: "invalid_args",
6465
+ status: 400,
6466
+ exitCode: EXIT_CODES.invalidArgs,
6467
+ details: { supportedFiles }
6468
+ });
6399
6469
  }
6400
- return `Agent Wiki/${trimmed}`;
6470
+ return `Agent Wiki/${fileName}`;
6471
+ }
6472
+ function normalizeWikiIndexPath(path) {
6473
+ return normalizeWikiPath(path, { supportedFiles: [supportedWikiIndexFile] });
6474
+ }
6475
+ function normalizeWikiLogPath(path = supportedWikiLogFile) {
6476
+ return normalizeWikiPath(path, { supportedFiles: [supportedWikiLogFile] });
6401
6477
  }
6402
6478
  function parseOptionalParentRef(value) {
6403
6479
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
@@ -6507,6 +6583,14 @@ function writePreflightError(status, action) {
6507
6583
  status: 403
6508
6584
  };
6509
6585
  }
6586
+ if (status.access === "append_only" && action !== "append") {
6587
+ return {
6588
+ code: "append_only_violation",
6589
+ message: `Agent markdown file is append-only and cannot be overwritten: ${status.path}`,
6590
+ suggestedAction: status.suggestedAction,
6591
+ status: 403
6592
+ };
6593
+ }
6510
6594
  if (action === "create") {
6511
6595
  if (status.exists) {
6512
6596
  return {
@@ -6518,7 +6602,7 @@ function writePreflightError(status, action) {
6518
6602
  }
6519
6603
  if (!status.canCreate) {
6520
6604
  return {
6521
- code: status.access === "append_only" ? "append_only_violation" : "agent_path_forbidden",
6605
+ code: "agent_path_forbidden",
6522
6606
  message: `Create is not allowed for ${status.path}.`,
6523
6607
  suggestedAction: status.suggestedAction,
6524
6608
  status: 403
@@ -6536,13 +6620,31 @@ function writePreflightError(status, action) {
6536
6620
  }
6537
6621
  if (!status.canUpdate) {
6538
6622
  return {
6539
- code: status.access === "append_only" ? "append_only_violation" : "agent_path_forbidden",
6623
+ code: "agent_path_forbidden",
6540
6624
  message: `Update is not allowed for ${status.path}.`,
6541
6625
  suggestedAction: status.suggestedAction,
6542
6626
  status: 403
6543
6627
  };
6544
6628
  }
6545
6629
  }
6630
+ if (action === "append") {
6631
+ if (!status.exists) {
6632
+ return {
6633
+ code: "agent_file_not_found",
6634
+ message: status.suggestedAction === "init" ? `Agent Wiki log is not initialized. Run wave osmd wiki init before append-log.` : `Agent markdown file does not exist: ${status.path}`,
6635
+ suggestedAction: status.suggestedAction,
6636
+ status: 404
6637
+ };
6638
+ }
6639
+ if (status.access !== "append_only" || !status.canAppend) {
6640
+ return {
6641
+ code: "append_only_violation",
6642
+ message: `Append is not allowed for ${status.path}.`,
6643
+ suggestedAction: status.suggestedAction,
6644
+ status: 403
6645
+ };
6646
+ }
6647
+ }
6546
6648
  return null;
6547
6649
  }
6548
6650
  function statusCodeForAgentError(code) {
@@ -6585,19 +6687,28 @@ async function runWriteFlow(params) {
6585
6687
  update: {
6586
6688
  operationName: "UpdateAgentMarkdownFile",
6587
6689
  field: "update_agent_markdown_file"
6690
+ },
6691
+ append: {
6692
+ operationName: "RecordAgentMarkdownLog",
6693
+ field: "record_agent_markdown_log"
6588
6694
  }
6589
6695
  }[params.action];
6696
+ const variables = params.action === "append" ? {
6697
+ organization_id: params.organizationId,
6698
+ path: status.data.path,
6699
+ content: params.content
6700
+ } : {
6701
+ organization_id: params.organizationId,
6702
+ path: status.data.path,
6703
+ parent_ref: status.data.parentRef ?? params.parentRef,
6704
+ content: params.content
6705
+ };
6590
6706
  return runAgentMarkdownMutation({
6591
6707
  command: params.command,
6592
6708
  operationName: mutation.operationName,
6593
6709
  runtimeOptions: params.runtimeOptions,
6594
6710
  field: mutation.field,
6595
- variables: {
6596
- organization_id: params.organizationId,
6597
- path: status.data.path,
6598
- parent_ref: status.data.parentRef ?? params.parentRef,
6599
- content: params.content
6600
- }
6711
+ variables
6601
6712
  });
6602
6713
  }
6603
6714
  function addContentOptions(command) {
@@ -6691,8 +6802,8 @@ function registerOsmdCommands(program) {
6691
6802
  })
6692
6803
  });
6693
6804
  });
6694
- const agent = osmd.command("agent").description(".agent overlay files writable by agents; supports notes.md and log.md");
6695
- agent.command("status <parent-ref> <file>").action(async (parentRef, file, _opts, cmd) => {
6805
+ const agent = osmd.command("agent").description(".agent overlay memory attached to canonical OSMD parents; supports notes.md");
6806
+ agent.command("status <parent-ref> <file>").description("Show .agent notes.md metadata without creating files").action(async (parentRef, file, _opts, cmd) => {
6696
6807
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6697
6808
  const result = await requestAgentMarkdownStatus({
6698
6809
  command: "osmd.agent.status",
@@ -6710,7 +6821,7 @@ function registerOsmdCommands(program) {
6710
6821
  })
6711
6822
  });
6712
6823
  });
6713
- agent.command("init <parent-ref>").action(async (parentRef, _opts, cmd) => {
6824
+ agent.command("init <parent-ref>").description("Idempotently initialize supported .agent files for a canonical OSMD parent").action(async (parentRef, _opts, cmd) => {
6714
6825
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6715
6826
  return runAgentMarkdownMutation({
6716
6827
  command: "osmd.agent.init",
@@ -6724,7 +6835,7 @@ function registerOsmdCommands(program) {
6724
6835
  }
6725
6836
  });
6726
6837
  });
6727
- agent.command("read <parent-ref> <file>").action(async (parentRef, file, _opts, cmd) => {
6838
+ agent.command("read <parent-ref> <file>").description("Read .agent notes.md without creating files").action(async (parentRef, file, _opts, cmd) => {
6728
6839
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6729
6840
  const result = await requestAgentMarkdownFile({
6730
6841
  command: "osmd.agent.read",
@@ -6742,7 +6853,9 @@ function registerOsmdCommands(program) {
6742
6853
  })
6743
6854
  });
6744
6855
  });
6745
- addContentOptions(agent.command("create <parent-ref> <file>")).action(
6856
+ addContentOptions(
6857
+ agent.command("create <parent-ref> <file>").description("Create .agent notes.md after status/permission preflight")
6858
+ ).action(
6746
6859
  async (parentRef, file, opts, cmd) => {
6747
6860
  const globals = cmd.optsWithGlobals();
6748
6861
  const content = await resolveContentInput(opts, globals);
@@ -6758,7 +6871,9 @@ function registerOsmdCommands(program) {
6758
6871
  });
6759
6872
  }
6760
6873
  );
6761
- addContentOptions(agent.command("update <parent-ref> <file>")).action(
6874
+ addContentOptions(
6875
+ agent.command("update <parent-ref> <file>").description("Update .agent notes.md after status/permission preflight")
6876
+ ).action(
6762
6877
  async (parentRef, file, opts, cmd) => {
6763
6878
  const globals = cmd.optsWithGlobals();
6764
6879
  const content = await resolveContentInput(opts, globals);
@@ -6774,8 +6889,21 @@ function registerOsmdCommands(program) {
6774
6889
  });
6775
6890
  }
6776
6891
  );
6777
- const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; first slice should use index.md and log.md");
6778
- wiki.command("status <path>").action(async (path, _opts, cmd) => {
6892
+ const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; supports index.md and append-only log.md");
6893
+ wiki.command("init").description("Idempotently initialize Agent Wiki system files").action(async function() {
6894
+ const { organizationId, runtimeOptions } = await resolveOsmdContext(this);
6895
+ return runAgentMarkdownMutation({
6896
+ command: "osmd.wiki.init",
6897
+ operationName: "InitAgentMarkdown",
6898
+ runtimeOptions,
6899
+ field: "init_agent_markdown",
6900
+ variables: {
6901
+ organization_id: organizationId,
6902
+ path: "Agent Wiki"
6903
+ }
6904
+ });
6905
+ });
6906
+ wiki.command("status <path>").description("Show Agent Wiki index.md or log.md metadata without creating files").action(async (path, _opts, cmd) => {
6779
6907
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6780
6908
  const result = await requestAgentMarkdownStatus({
6781
6909
  command: "osmd.wiki.status",
@@ -6792,7 +6920,7 @@ function registerOsmdCommands(program) {
6792
6920
  })
6793
6921
  });
6794
6922
  });
6795
- wiki.command("read <path>").action(async (path, _opts, cmd) => {
6923
+ wiki.command("read <path>").description("Read Agent Wiki index.md or log.md without creating files").action(async (path, _opts, cmd) => {
6796
6924
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6797
6925
  const result = await requestAgentMarkdownFile({
6798
6926
  command: "osmd.wiki.read",
@@ -6809,13 +6937,13 @@ function registerOsmdCommands(program) {
6809
6937
  })
6810
6938
  });
6811
6939
  });
6812
- wiki.command("children [path]").action(async (path, _opts, cmd) => {
6940
+ wiki.command("children [path]").description("List Agent Wiki children through backend metadata").action(async (path, _opts, cmd) => {
6813
6941
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6814
6942
  const result = await requestAgentMarkdownChildren({
6815
6943
  command: "osmd.wiki.children",
6816
6944
  runtimeOptions,
6817
6945
  organizationId,
6818
- path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path) : "Agent Wiki",
6946
+ path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path, { allowRoot: true }) : "Agent Wiki",
6819
6947
  source: "agent_wiki"
6820
6948
  });
6821
6949
  return printEnvelopeAndExit({
@@ -6827,7 +6955,9 @@ function registerOsmdCommands(program) {
6827
6955
  })
6828
6956
  });
6829
6957
  });
6830
- addContentOptions(wiki.command("create <path>")).action(async (path, opts, cmd) => {
6958
+ addContentOptions(
6959
+ wiki.command("create <path>").description("Create Agent Wiki index.md after status/permission preflight")
6960
+ ).action(async (path, opts, cmd) => {
6831
6961
  const globals = cmd.optsWithGlobals();
6832
6962
  const content = await resolveContentInput(opts, globals);
6833
6963
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
@@ -6836,11 +6966,13 @@ function registerOsmdCommands(program) {
6836
6966
  action: "create",
6837
6967
  runtimeOptions,
6838
6968
  organizationId,
6839
- path: normalizeWikiPath(path),
6969
+ path: normalizeWikiIndexPath(path),
6840
6970
  content
6841
6971
  });
6842
6972
  });
6843
- addContentOptions(wiki.command("update <path>")).action(async (path, opts, cmd) => {
6973
+ addContentOptions(
6974
+ wiki.command("update <path>").description("Update Agent Wiki index.md after status/permission preflight")
6975
+ ).action(async (path, opts, cmd) => {
6844
6976
  const globals = cmd.optsWithGlobals();
6845
6977
  const content = await resolveContentInput(opts, globals);
6846
6978
  const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
@@ -6849,7 +6981,22 @@ function registerOsmdCommands(program) {
6849
6981
  action: "update",
6850
6982
  runtimeOptions,
6851
6983
  organizationId,
6852
- path: normalizeWikiPath(path),
6984
+ path: normalizeWikiIndexPath(path),
6985
+ content
6986
+ });
6987
+ });
6988
+ addContentOptions(
6989
+ wiki.command("append-log [path]").description("Append to Agent Wiki log.md after status/permission preflight")
6990
+ ).action(async (path, opts, cmd) => {
6991
+ const globals = cmd.optsWithGlobals();
6992
+ const content = await resolveContentInput(opts, globals);
6993
+ const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
6994
+ return runWriteFlow({
6995
+ command: "osmd.wiki.append-log",
6996
+ action: "append",
6997
+ runtimeOptions,
6998
+ organizationId,
6999
+ path: normalizeWikiLogPath(typeof path === "string" && path.trim() !== "" ? path : void 0),
6853
7000
  content
6854
7001
  });
6855
7002
  });
@@ -6899,23 +7046,21 @@ function buildCli(options) {
6899
7046
 
6900
7047
  // src/index.ts
6901
7048
  function printCliFailure(params) {
6902
- printEnvelopeAndExit({
6903
- envelope: {
6904
- ok: false,
6905
- command: "cli",
6906
- status: params.status,
6907
- data: null,
6908
- error: {
6909
- code: params.code,
6910
- message: params.message,
6911
- details: params.details ?? {}
6912
- },
6913
- meta: {
6914
- requestId: "local_error"
6915
- }
7049
+ printEnvelope({
7050
+ ok: false,
7051
+ command: "cli",
7052
+ status: params.status,
7053
+ data: null,
7054
+ error: {
7055
+ code: params.code,
7056
+ message: params.message,
7057
+ details: params.details ?? {}
6916
7058
  },
6917
- exitCode: params.exitCode
7059
+ meta: {
7060
+ requestId: "local_error"
7061
+ }
6918
7062
  });
7063
+ process.exitCode = params.exitCode;
6919
7064
  }
6920
7065
  async function main() {
6921
7066
  const program = buildCli();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ted-galago/wave-cli",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "wave": "dist/index.js"