kollab 0.1.28 → 0.1.29

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
@@ -12238,10 +12238,10 @@ function parseJsonErrorBody(raw) {
12238
12238
  return void 0;
12239
12239
  }
12240
12240
  }
12241
- function buildCreditReservedHint(input) {
12242
- const reserved = input.code === KOLLAB_CREDIT_RESERVED_CODE || String(input.error ?? "").toLowerCase().includes("credits are temporarily reserved");
12241
+ function buildCreditReservedHint(input2) {
12242
+ const reserved = input2.code === KOLLAB_CREDIT_RESERVED_CODE || String(input2.error ?? "").toLowerCase().includes("credits are temporarily reserved");
12243
12243
  if (!reserved) return void 0;
12244
- const wait = input.retryAfterSeconds ? `about ${input.retryAfterSeconds}s` : "a short while";
12244
+ const wait = input2.retryAfterSeconds ? `about ${input2.retryAfterSeconds}s` : "a short while";
12245
12245
  return `Workspace credits are temporarily held by in-flight or just-interrupted requests in this space; this is not a balance problem. Wait ${wait} and retry the same command. If it keeps happening, check for other runs in this space.`;
12246
12246
  }
12247
12247
 
@@ -14175,67 +14175,67 @@ function registerTaskCreateCommand(task) {
14175
14175
  var import_promises2 = require("fs/promises");
14176
14176
 
14177
14177
  // src/lib/ask-command.ts
14178
- function buildAskRequestBody(spaceId, input) {
14178
+ function buildAskRequestBody(spaceId, input2) {
14179
14179
  const qaQueryOption = {};
14180
- if (input.projectId) {
14181
- qaQueryOption.knowledgeBaseIds = [input.projectId];
14180
+ if (input2.projectId) {
14181
+ qaQueryOption.knowledgeBaseIds = [input2.projectId];
14182
14182
  }
14183
- if (input.fileIds && input.fileIds.length > 0) {
14184
- qaQueryOption.fileIds = input.fileIds;
14183
+ if (input2.fileIds && input2.fileIds.length > 0) {
14184
+ qaQueryOption.fileIds = input2.fileIds;
14185
14185
  }
14186
14186
  const body = {
14187
- question: input.question,
14188
- message: input.question,
14187
+ question: input2.question,
14188
+ message: input2.question,
14189
14189
  spaceId,
14190
- conversationId: input.conversationId ?? "",
14190
+ conversationId: input2.conversationId ?? "",
14191
14191
  qaQueryOption,
14192
- agent_id: input.agentId ?? "default",
14193
- agent_mentioned: hasKollabAgentMention(input.question)
14192
+ agent_id: input2.agentId ?? "default",
14193
+ agent_mentioned: hasKollabAgentMention(input2.question)
14194
14194
  };
14195
- if (input.projectId) {
14196
- body.projectId = input.projectId;
14195
+ if (input2.projectId) {
14196
+ body.projectId = input2.projectId;
14197
14197
  }
14198
- if (input.modelTier) {
14199
- body.model_tier = input.modelTier;
14198
+ if (input2.modelTier) {
14199
+ body.model_tier = input2.modelTier;
14200
14200
  }
14201
- if (input.byokCredentialId) {
14202
- body.byok_credential_id = input.byokCredentialId;
14201
+ if (input2.byokCredentialId) {
14202
+ body.byok_credential_id = input2.byokCredentialId;
14203
14203
  }
14204
- if (input.mcpServerIds && input.mcpServerIds.length > 0) {
14205
- body.mcp_server_ids = input.mcpServerIds;
14204
+ if (input2.mcpServerIds && input2.mcpServerIds.length > 0) {
14205
+ body.mcp_server_ids = input2.mcpServerIds;
14206
14206
  }
14207
- if (input.uploadedFileKeys && input.uploadedFileKeys.length > 0) {
14208
- body.uploaded_file_keys = input.uploadedFileKeys;
14207
+ if (input2.uploadedFileKeys && input2.uploadedFileKeys.length > 0) {
14208
+ body.uploaded_file_keys = input2.uploadedFileKeys;
14209
14209
  }
14210
- if (Array.isArray(input.attachments) && input.attachments.length > 0) {
14211
- body.attachments = input.attachments;
14210
+ if (Array.isArray(input2.attachments) && input2.attachments.length > 0) {
14211
+ body.attachments = input2.attachments;
14212
14212
  }
14213
- if (input.quotedMessageId) {
14214
- body.quotedMessageId = input.quotedMessageId;
14213
+ if (input2.quotedMessageId) {
14214
+ body.quotedMessageId = input2.quotedMessageId;
14215
14215
  }
14216
- if (input.remixShareToken) {
14216
+ if (input2.remixShareToken) {
14217
14217
  body.remix_source = {
14218
14218
  source_type: "share",
14219
- share_token: input.remixShareToken,
14220
- ...input.remixSourceTaskTitle ? { source_task_title: input.remixSourceTaskTitle } : {}
14219
+ share_token: input2.remixShareToken,
14220
+ ...input2.remixSourceTaskTitle ? { source_task_title: input2.remixSourceTaskTitle } : {}
14221
14221
  };
14222
14222
  }
14223
- if (input.composerMode) {
14224
- body.composer_mode = input.composerMode;
14223
+ if (input2.composerMode) {
14224
+ body.composer_mode = input2.composerMode;
14225
14225
  }
14226
- if (input.composerModeOptions && Object.keys(input.composerModeOptions).length > 0) {
14227
- body.composer_mode_options = input.composerModeOptions;
14226
+ if (input2.composerModeOptions && Object.keys(input2.composerModeOptions).length > 0) {
14227
+ body.composer_mode_options = input2.composerModeOptions;
14228
14228
  }
14229
14229
  return body;
14230
14230
  }
14231
- function buildAnswerQuestionRequestBody(input) {
14231
+ function buildAnswerQuestionRequestBody(input2) {
14232
14232
  return {
14233
- conversationId: input.conversationId,
14234
- tool_use_id: input.toolUseId,
14235
- answers: input.answers,
14236
- agent_id: input.agentId ?? "default",
14237
- ...input.modelTier ? { model_tier: input.modelTier } : {},
14238
- ...input.byokCredentialId ? { byok_credential_id: input.byokCredentialId } : {}
14233
+ conversationId: input2.conversationId,
14234
+ tool_use_id: input2.toolUseId,
14235
+ answers: input2.answers,
14236
+ agent_id: input2.agentId ?? "default",
14237
+ ...input2.modelTier ? { model_tier: input2.modelTier } : {},
14238
+ ...input2.byokCredentialId ? { byok_credential_id: input2.byokCredentialId } : {}
14239
14239
  };
14240
14240
  }
14241
14241
  function hasKollabAgentMention(text2) {
@@ -14679,20 +14679,20 @@ function mimeFromPath2(filePath) {
14679
14679
  };
14680
14680
  return map[ext] ?? "application/octet-stream";
14681
14681
  }
14682
- async function uploadTaskAttachmentBytes(creds, input) {
14683
- if (!input.conversationId.trim()) {
14682
+ async function uploadTaskAttachmentBytes(creds, input2) {
14683
+ if (!input2.conversationId.trim()) {
14684
14684
  throw new Error("conversationId is required");
14685
14685
  }
14686
- if (input.content.byteLength > MAX_FILE_BYTES2) {
14686
+ if (input2.content.byteLength > MAX_FILE_BYTES2) {
14687
14687
  throw new Error(
14688
- `File exceeds the 500 MB upload limit (${input.content.byteLength} bytes): ${input.fileName}`
14688
+ `File exceeds the 500 MB upload limit (${input2.content.byteLength} bytes): ${input2.fileName}`
14689
14689
  );
14690
14690
  }
14691
- const fallbackMimeType = input.contentType || mimeFromPath2(input.fileName);
14691
+ const fallbackMimeType = input2.contentType || mimeFromPath2(input2.fileName);
14692
14692
  const uploadUrlResult = await api(creds, "POST", "/skills/chat/upload-url", {
14693
- conversation_id: input.conversationId,
14694
- file_name: input.fileName,
14695
- file_size: input.content.byteLength
14693
+ conversation_id: input2.conversationId,
14694
+ file_name: input2.fileName,
14695
+ file_size: input2.content.byteLength
14696
14696
  });
14697
14697
  if (!uploadUrlResult.ok || !uploadUrlResult.data) {
14698
14698
  throw new Error(uploadUrlResult.error ?? "Failed to get upload URL");
@@ -14706,11 +14706,11 @@ async function uploadTaskAttachmentBytes(creds, input) {
14706
14706
  file_name: uploadedFileName
14707
14707
  } = uploadUrlResult.data;
14708
14708
  const resolvedMimeType = contentType || fallbackMimeType;
14709
- const resolvedFileName = uploadedFileName || input.fileName;
14709
+ const resolvedFileName = uploadedFileName || input2.fileName;
14710
14710
  const putResponse = await fetch(uploadUrl, {
14711
14711
  method: "PUT",
14712
14712
  headers: { "Content-Type": resolvedMimeType },
14713
- body: input.content
14713
+ body: input2.content
14714
14714
  });
14715
14715
  if (!putResponse.ok) {
14716
14716
  throw new Error(
@@ -14722,12 +14722,12 @@ async function uploadTaskAttachmentBytes(creds, input) {
14722
14722
  const syncResult = await api(
14723
14723
  creds,
14724
14724
  "POST",
14725
- `/artifacts/conversation/${input.conversationId}/sync-upload`,
14725
+ `/artifacts/conversation/${input2.conversationId}/sync-upload`,
14726
14726
  {
14727
14727
  file_name: resolvedFileName,
14728
14728
  s3_key: fileKey,
14729
14729
  s3_bucket: s3Bucket,
14730
- size: input.content.byteLength,
14730
+ size: input2.content.byteLength,
14731
14731
  content_type: resolvedMimeType
14732
14732
  }
14733
14733
  );
@@ -14752,7 +14752,7 @@ async function uploadTaskAttachmentBytes(creds, input) {
14752
14752
  // ignores these extra fields, while existing scripts may still read them.
14753
14753
  file_key: fileKey,
14754
14754
  file_name: resolvedFileName,
14755
- file_size: input.content.byteLength,
14755
+ file_size: input2.content.byteLength,
14756
14756
  mime_type: resolvedMimeType,
14757
14757
  download_url: downloadUrl,
14758
14758
  s3_bucket: s3Bucket,
@@ -14761,13 +14761,13 @@ async function uploadTaskAttachmentBytes(creds, input) {
14761
14761
  return {
14762
14762
  fileKey,
14763
14763
  filename: resolvedFileName,
14764
- size: input.content.byteLength,
14764
+ size: input2.content.byteLength,
14765
14765
  mime: resolvedMimeType,
14766
- conversationId: input.conversationId,
14766
+ conversationId: input2.conversationId,
14767
14767
  hint: "Pass fileKey to `task ask --uploaded-file-keys` and attachments to `task ask --attachments`.",
14768
14768
  attachments: [attachmentItem],
14769
14769
  uploadedFileKeys: [fileKey],
14770
- taskAskExample: `kollab task ask --conversation-id ${input.conversationId} --question "Analyse this file" --uploaded-file-keys '["${fileKey}"]' --attachments '${JSON.stringify([attachmentItem])}'`
14770
+ taskAskExample: `kollab task ask --conversation-id ${input2.conversationId} --question "Analyse this file" --uploaded-file-keys '["${fileKey}"]' --attachments '${JSON.stringify([attachmentItem])}'`
14771
14771
  };
14772
14772
  }
14773
14773
  function registerTaskUploadCommand(task) {
@@ -14867,7 +14867,7 @@ function registerTaskAskCommand(task) {
14867
14867
  "--uploaded-file-keys"
14868
14868
  ) : void 0;
14869
14869
  const existingAttachments = opts.attachments !== void 0 ? parseJsonOption(opts.attachments, "--attachments") : void 0;
14870
- const input = {
14870
+ const input2 = {
14871
14871
  question: resolvedQuestion.question,
14872
14872
  conversationId: opts.conversationId || process.env.CURRENT_CONVERSATION_ID || void 0,
14873
14873
  projectId: opts.projectId,
@@ -14890,13 +14890,13 @@ function registerTaskAskCommand(task) {
14890
14890
  await materializeLargeQuestionAsAttachment(
14891
14891
  creds,
14892
14892
  spaceId,
14893
- input,
14893
+ input2,
14894
14894
  resolvedQuestion
14895
14895
  );
14896
14896
  const result = await runChatTurn(creds, {
14897
14897
  path: "/skills/chat/stream",
14898
- body: buildAskRequestBody(spaceId, input),
14899
- conversationId: input.conversationId
14898
+ body: buildAskRequestBody(spaceId, input2),
14899
+ conversationId: input2.conversationId
14900
14900
  });
14901
14901
  printResult(result);
14902
14902
  }
@@ -14917,34 +14917,34 @@ async function resolveAskQuestion(opts) {
14917
14917
  }
14918
14918
  return { question: opts.question ?? "" };
14919
14919
  }
14920
- async function materializeLargeQuestionAsAttachment(creds, spaceId, input, resolvedQuestion) {
14921
- if (!shouldMaterializeLargeQuestion(input.question)) {
14920
+ async function materializeLargeQuestionAsAttachment(creds, spaceId, input2, resolvedQuestion) {
14921
+ if (!shouldMaterializeLargeQuestion(input2.question)) {
14922
14922
  return;
14923
14923
  }
14924
14924
  const conversationId = await ensureConversationForLargeQuestion(
14925
14925
  creds,
14926
14926
  spaceId,
14927
- input
14927
+ input2
14928
14928
  );
14929
14929
  const uploaded = await uploadTaskAttachmentBytes(creds, {
14930
14930
  conversationId,
14931
14931
  fileName: buildLargeQuestionFileName(resolvedQuestion.sourceFilePath),
14932
- content: new TextEncoder().encode(input.question),
14932
+ content: new TextEncoder().encode(input2.question),
14933
14933
  contentType: "text/plain;charset=utf-8"
14934
14934
  });
14935
- input.conversationId = conversationId;
14936
- input.question = CLI_LARGE_QUESTION_ATTACHMENT_PROMPT;
14937
- input.uploadedFileKeys = [
14938
- ...input.uploadedFileKeys ?? [],
14935
+ input2.conversationId = conversationId;
14936
+ input2.question = CLI_LARGE_QUESTION_ATTACHMENT_PROMPT;
14937
+ input2.uploadedFileKeys = [
14938
+ ...input2.uploadedFileKeys ?? [],
14939
14939
  ...uploaded.uploadedFileKeys
14940
14940
  ];
14941
- input.attachments = [
14942
- ...normalizeAttachmentArray(input.attachments),
14941
+ input2.attachments = [
14942
+ ...normalizeAttachmentArray(input2.attachments),
14943
14943
  ...uploaded.attachments
14944
14944
  ];
14945
14945
  }
14946
- async function ensureConversationForLargeQuestion(creds, spaceId, input) {
14947
- const existingConversationId = input.conversationId?.trim();
14946
+ async function ensureConversationForLargeQuestion(creds, spaceId, input2) {
14947
+ const existingConversationId = input2.conversationId?.trim();
14948
14948
  if (existingConversationId) {
14949
14949
  return existingConversationId;
14950
14950
  }
@@ -14952,7 +14952,7 @@ async function ensureConversationForLargeQuestion(creds, spaceId, input) {
14952
14952
  creds,
14953
14953
  "POST",
14954
14954
  "/qa/conversation",
14955
- buildLargeQuestionConversationPayload(spaceId, input)
14955
+ buildLargeQuestionConversationPayload(spaceId, input2)
14956
14956
  );
14957
14957
  if (!createResult.ok) {
14958
14958
  throw new Error(
@@ -14968,13 +14968,13 @@ async function ensureConversationForLargeQuestion(creds, spaceId, input) {
14968
14968
  function shouldMaterializeLargeQuestion(question) {
14969
14969
  return Buffer.byteLength(question, "utf8") > CLI_DIRECT_QUESTION_MAX_BYTES;
14970
14970
  }
14971
- function buildLargeQuestionConversationPayload(spaceId, input) {
14971
+ function buildLargeQuestionConversationPayload(spaceId, input2) {
14972
14972
  return {
14973
14973
  question: "",
14974
14974
  spaceId,
14975
- ...input.projectId ? { parentId: input.projectId } : {},
14976
- ...input.modelTier ? { modelTier: input.modelTier } : {},
14977
- ...input.composerMode ? { composerMode: input.composerMode } : {}
14975
+ ...input2.projectId ? { parentId: input2.projectId } : {},
14976
+ ...input2.modelTier ? { modelTier: input2.modelTier } : {},
14977
+ ...input2.composerMode ? { composerMode: input2.composerMode } : {}
14978
14978
  };
14979
14979
  }
14980
14980
  function buildLargeQuestionFileName(sourceFilePath) {
@@ -14996,7 +14996,7 @@ function registerTaskAnswerQuestionCommand(task) {
14996
14996
  ).requiredOption("--conversation-id <uuid>", "Conversation ID").requiredOption("--tool-use-id <id>", "Questionnaire tool_use_id").requiredOption("--answers <json>", "Answers JSON object").option("--model-tier <tier>", MODEL_SELECTION_OPTION_DESCRIPTION).option("--byok-credential-id <uuid>", "Opaque workspace BYOK credential ID").option("--agent-id <uuid>", "Agent override").action(
14997
14997
  async (opts) => {
14998
14998
  const answers = parseQuestionnaireAnswers(opts.answers);
14999
- const input = {
14999
+ const input2 = {
15000
15000
  conversationId: opts.conversationId,
15001
15001
  toolUseId: opts.toolUseId,
15002
15002
  answers,
@@ -15007,7 +15007,7 @@ function registerTaskAnswerQuestionCommand(task) {
15007
15007
  const creds = requireCredentials();
15008
15008
  const result = await runChatTurn(creds, {
15009
15009
  path: "/skills/chat/answer-question",
15010
- body: buildAnswerQuestionRequestBody(input),
15010
+ body: buildAnswerQuestionRequestBody(input2),
15011
15011
  conversationId: opts.conversationId
15012
15012
  });
15013
15013
  printResult(result);
@@ -15342,15 +15342,15 @@ async function fireRelay(creds, spaceId, conversationId, relayQuestion, projectI
15342
15342
  }
15343
15343
  return { accepted: false, attempts: RELAY_RETRY_MAX, ack: null, lastError };
15344
15344
  }
15345
- async function runRelayTest(creds, spaceId, input) {
15346
- let conversationId = input.conversationId ?? null;
15345
+ async function runRelayTest(creds, spaceId, input2) {
15346
+ let conversationId = input2.conversationId ?? null;
15347
15347
  if (!conversationId) {
15348
15348
  conversationId = await createConversation(
15349
15349
  creds,
15350
15350
  spaceId,
15351
- input.question,
15352
- input.projectId,
15353
- input.modelTier
15351
+ input2.question,
15352
+ input2.projectId,
15353
+ input2.modelTier
15354
15354
  );
15355
15355
  }
15356
15356
  if (!conversationId) {
@@ -15371,10 +15371,10 @@ async function runRelayTest(creds, spaceId, input) {
15371
15371
  }
15372
15372
  const controller = new AbortController();
15373
15373
  const mainBody = buildAskRequestBody(spaceId, {
15374
- question: input.question,
15374
+ question: input2.question,
15375
15375
  conversationId,
15376
- projectId: input.projectId,
15377
- modelTier: input.modelTier
15376
+ projectId: input2.projectId,
15377
+ modelTier: input2.modelTier
15378
15378
  });
15379
15379
  const startedAt = Date.now();
15380
15380
  let mainCompleted = false;
@@ -15390,7 +15390,7 @@ async function runRelayTest(creds, spaceId, input) {
15390
15390
  }).catch(() => {
15391
15391
  mainCompleted = mainCompleted || false;
15392
15392
  });
15393
- const generatingDeadline = Date.now() + input.generatingWaitMs;
15393
+ const generatingDeadline = Date.now() + input2.generatingWaitMs;
15394
15394
  let sawGenerating = false;
15395
15395
  while (Date.now() <= generatingDeadline && !mainCompleted) {
15396
15396
  const status = await getGenerationStatus(creds, conversationId);
@@ -15400,11 +15400,11 @@ async function runRelayTest(creds, spaceId, input) {
15400
15400
  }
15401
15401
  await sleep4(STATUS_POLL_INTERVAL_MS);
15402
15402
  }
15403
- if (sawGenerating && input.relayAfterMs > 0) {
15404
- await sleep4(input.relayAfterMs);
15403
+ if (sawGenerating && input2.relayAfterMs > 0) {
15404
+ await sleep4(input2.relayAfterMs);
15405
15405
  }
15406
- const relayCount = Math.max(1, input.relayCount ?? 1);
15407
- const relayIntervalMs = input.relayIntervalMs ?? 1500;
15406
+ const relayCount = Math.max(1, input2.relayCount ?? 1);
15407
+ const relayIntervalMs = input2.relayIntervalMs ?? 1500;
15408
15408
  const relays = [];
15409
15409
  let relay = {
15410
15410
  accepted: false,
@@ -15414,14 +15414,14 @@ async function runRelayTest(creds, spaceId, input) {
15414
15414
  };
15415
15415
  const runId = (0, import_node_crypto2.randomUUID)();
15416
15416
  for (let i = 1; i <= relayCount; i += 1) {
15417
- const q = `${input.relayQuestion} [relay-${runId}-${i}]`;
15417
+ const q = `${input2.relayQuestion} [relay-${runId}-${i}]`;
15418
15418
  const r = await fireRelay(
15419
15419
  creds,
15420
15420
  spaceId,
15421
15421
  conversationId,
15422
15422
  q,
15423
- input.projectId,
15424
- input.modelTier
15423
+ input2.projectId,
15424
+ input2.modelTier
15425
15425
  );
15426
15426
  if (i === 1) {
15427
15427
  relay = r;
@@ -15441,7 +15441,7 @@ async function runRelayTest(creds, spaceId, input) {
15441
15441
  await sleep4(relayIntervalMs);
15442
15442
  }
15443
15443
  }
15444
- const remainingMs = Math.max(0, input.maxWaitMs - (Date.now() - startedAt));
15444
+ const remainingMs = Math.max(0, input2.maxWaitMs - (Date.now() - startedAt));
15445
15445
  let timeout;
15446
15446
  const winner = await Promise.race([
15447
15447
  mainPromise.then(() => "completed"),
@@ -15458,7 +15458,7 @@ async function runRelayTest(creds, spaceId, input) {
15458
15458
  assessRelayMessages(relays, messages);
15459
15459
  finalGenerationStatus = await getGenerationStatus(creds, conversationId);
15460
15460
  if (finalGenerationStatus !== "generating" && relays.every((r) => !r.accepted || r.answered || r.explicitlyFailed)) break;
15461
- const remaining = input.maxWaitMs - (Date.now() - startedAt);
15461
+ const remaining = input2.maxWaitMs - (Date.now() - startedAt);
15462
15462
  if (remaining <= 0) break;
15463
15463
  await sleep4(Math.min(STATUS_POLL_INTERVAL_MS, remaining));
15464
15464
  } while (true);
@@ -17076,10 +17076,10 @@ function targetsSystemRoot(rest) {
17076
17076
  return t === "" || t === "/" || t === "~" || t === "/*" || /^[A-Za-z]:$/.test(t);
17077
17077
  });
17078
17078
  }
17079
- function hasUnbalancedQuotes(input) {
17079
+ function hasUnbalancedQuotes(input2) {
17080
17080
  let quote = null;
17081
- for (let i = 0; i < input.length; i += 1) {
17082
- const ch = input[i];
17081
+ for (let i = 0; i < input2.length; i += 1) {
17082
+ const ch = input2[i];
17083
17083
  if (ch === "\\" && quote !== "'") {
17084
17084
  i += 1;
17085
17085
  continue;
@@ -19184,8 +19184,8 @@ function listTools() {
19184
19184
  outputSchema: MCP_TOOL_OUTPUT_SCHEMAS[name]
19185
19185
  }));
19186
19186
  }
19187
- async function runMcpServer(input = process.stdin, output = process.stdout) {
19188
- const readline = (0, import_node_readline.createInterface)({ input, crlfDelay: Infinity });
19187
+ async function runMcpServer(input2 = process.stdin, output = process.stdout) {
19188
+ const readline = (0, import_node_readline.createInterface)({ input: input2, crlfDelay: Infinity });
19189
19189
  const write = (message) => {
19190
19190
  output.write(`${JSON.stringify(message)}
19191
19191
  `);
@@ -20065,8 +20065,60 @@ function registerUserCommands(program2) {
20065
20065
  });
20066
20066
  }
20067
20067
 
20068
+ // src/commands/site-platform.ts
20069
+ var import_node_fs5 = require("fs");
20070
+ function input(file) {
20071
+ return JSON.parse((0, import_node_fs5.readFileSync)(file === "-" ? 0 : file, "utf8"));
20072
+ }
20073
+ function registerSitePlatformCommands(program2) {
20074
+ const data2 = program2.command("data").description("Space collections, records and committed change feed");
20075
+ for (const action of ["collections", "configure", "list", "get", "save", "delete", "changes"]) {
20076
+ const command = data2.command(action).requiredOption("--app <id>", "Hosted App ID");
20077
+ if (action !== "collections") command.requiredOption("--collection <name>", "Collection name");
20078
+ if (["get", "delete"].includes(action)) command.requiredOption("--id <id>", "Record ID");
20079
+ if (["configure", "save"].includes(action)) command.requiredOption("--file <path>", "JSON file or - for stdin");
20080
+ command.option("--after <cursor>").option("--upper <cursor>").option("--sort <field>").option("--order <direction>").option("--revision <revision>").option("--limit <count>");
20081
+ command.action(async (options) => {
20082
+ const credentials = requireCredentials();
20083
+ const space = requireSpaceId(credentials);
20084
+ const base = `/spaces/${encodeURIComponent(space)}/site-platform/apps/${encodeURIComponent(options.app)}/collections`;
20085
+ const resource = `${base}/${encodeURIComponent(options.collection ?? "")}`;
20086
+ const query = new URLSearchParams(Object.fromEntries(["after", "upper", "sort", "order", "revision", "limit"].filter((key) => options[key] !== void 0).map((key) => [key, options[key]])));
20087
+ const path13 = action === "collections" ? base : action === "configure" ? resource : action === "changes" ? `${resource}/changes` : `${resource}/records${["get", "delete"].includes(action) ? `/${encodeURIComponent(options.id)}` : ""}`;
20088
+ printResult(await api(credentials, ["configure"].includes(action) ? "PUT" : action === "save" ? "POST" : action === "delete" ? "DELETE" : "GET", `${path13}?${query}`, options.file ? input(options.file) : void 0));
20089
+ });
20090
+ }
20091
+ const mail = program2.command("mail").description("Space mailbox, verified destinations, send and delivery records");
20092
+ mail.command("mailbox").action(async () => {
20093
+ const c = requireCredentials();
20094
+ printResult(await api(c, "POST", `/spaces/${encodeURIComponent(requireSpaceId(c))}/site-platform/mailbox`));
20095
+ });
20096
+ for (const action of ["list", "get", "status", "send"]) {
20097
+ const command = mail.command(action).requiredOption("--mailbox <id>", "Mailbox ID");
20098
+ if (["get", "status"].includes(action)) command.requiredOption("--id <id>", "Message ID");
20099
+ if (action === "send") command.requiredOption("--file <path>", "JSON: recipientIds, subject, text, idempotencyKey");
20100
+ command.option("--after <cursor>").option("--limit <count>").action(async (options) => {
20101
+ const c = requireCredentials();
20102
+ const query = new URLSearchParams(Object.fromEntries(["after", "limit"].filter((key) => options[key] !== void 0).map((key) => [key, options[key]])));
20103
+ const path13 = `/spaces/${encodeURIComponent(requireSpaceId(c))}/site-platform/mailboxes/${encodeURIComponent(options.mailbox)}/messages${options.id ? `/${encodeURIComponent(options.id)}` : ""}`;
20104
+ printResult(await api(c, action === "send" ? "POST" : "GET", `${path13}?${query}`, options.file ? input(options.file) : void 0));
20105
+ });
20106
+ }
20107
+ const recipient = mail.command("recipient");
20108
+ for (const action of ["list", "request", "verify"]) {
20109
+ const cmd = recipient.command(action);
20110
+ if (action === "request") cmd.requiredOption("--address <address>");
20111
+ if (action === "verify") cmd.requiredOption("--id <id>").requiredOption("--file <path>", "JSON containing code; - for stdin");
20112
+ cmd.action(async (options) => {
20113
+ const c = requireCredentials();
20114
+ const path13 = `/spaces/${encodeURIComponent(requireSpaceId(c))}/site-platform/recipients${action === "verify" ? `/${encodeURIComponent(options.id)}/verify` : ""}`;
20115
+ printResult(await api(c, action === "list" ? "GET" : "POST", path13, action === "request" ? { address: options.address } : options.file ? input(options.file) : void 0));
20116
+ });
20117
+ }
20118
+ }
20119
+
20068
20120
  // src/commands/app.ts
20069
- var import_node_fs6 = require("fs");
20121
+ var import_node_fs7 = require("fs");
20070
20122
  var import_node_path4 = require("path");
20071
20123
 
20072
20124
  // src/auth/hosted-app-credentials.ts
@@ -20091,7 +20143,7 @@ async function requireHostedAppCredentials() {
20091
20143
  }
20092
20144
 
20093
20145
  // src/commands/app-services.ts
20094
- var import_node_fs5 = require("fs");
20146
+ var import_node_fs6 = require("fs");
20095
20147
  function registerHostedSiteCommands(app) {
20096
20148
  const services = app.command("services").description("Configure shared forms and news for a static site (no function or compute slot)");
20097
20149
  for (const action of ["info", "enable", "disable", "delete-data"]) {
@@ -20113,7 +20165,7 @@ function registerHostedSiteCommands(app) {
20113
20165
  services.command("restore").requiredOption("--id <appId>", "Empty destination App ID").requiredOption("--file <path>", "Exported site-services.json").action(async (options) => {
20114
20166
  try {
20115
20167
  const credentials = await requireHostedAppCredentials();
20116
- printResult(await api(credentials, "POST", `/hosted-apps/${encodeURIComponent(options.id)}/services/restore`, JSON.parse((0, import_node_fs5.readFileSync)(options.file, "utf8"))));
20168
+ printResult(await api(credentials, "POST", `/hosted-apps/${encodeURIComponent(options.id)}/services/restore`, JSON.parse((0, import_node_fs6.readFileSync)(options.file, "utf8"))));
20117
20169
  } catch (error) {
20118
20170
  emitError(error instanceof Error ? error.message : String(error));
20119
20171
  }
@@ -20129,7 +20181,7 @@ function registerHostedSiteCommands(app) {
20129
20181
  form.command("verify").requiredOption("--id <appId>", "Hosted App ID").description("Read the six digit code from stdin").action(async (options) => {
20130
20182
  try {
20131
20183
  if (process.stdin.isTTY) throw new Error("Pass the verification code through stdin");
20132
- const code = (0, import_node_fs5.readFileSync)(0, "utf8").trim();
20184
+ const code = (0, import_node_fs6.readFileSync)(0, "utf8").trim();
20133
20185
  printResult(await api(await requireHostedAppCredentials(), "POST", `/hosted-apps/${encodeURIComponent(options.id)}/services/forms/contact/verify`, { code }));
20134
20186
  } catch (error) {
20135
20187
  emitError(error instanceof Error ? error.message : String(error));
@@ -20151,7 +20203,7 @@ function registerHostedSiteCommands(app) {
20151
20203
  const news = app.command("news").description("Manage the news collection; public reads show published records only");
20152
20204
  news.command("save").requiredOption("--id <appId>", "Hosted App ID").requiredOption("--file <path>", "JSON: optional id, title, body, status (draft/published)").action(async (options) => {
20153
20205
  try {
20154
- printResult(await api(await requireHostedAppCredentials(), "PUT", `/hosted-apps/${encodeURIComponent(options.id)}/services/collections/news/documents`, JSON.parse((0, import_node_fs5.readFileSync)(options.file, "utf8"))));
20206
+ printResult(await api(await requireHostedAppCredentials(), "PUT", `/hosted-apps/${encodeURIComponent(options.id)}/services/collections/news/documents`, JSON.parse((0, import_node_fs6.readFileSync)(options.file, "utf8"))));
20155
20207
  } catch (error) {
20156
20208
  emitError(error instanceof Error ? error.message : String(error));
20157
20209
  }
@@ -20352,12 +20404,12 @@ async function createBlankTask(creds, spaceId, projectId) {
20352
20404
  return readResourceId(requireApiData(result, "Create Hosted App task"), "task");
20353
20405
  }
20354
20406
  async function resolveHostedAppSource(creds, spaceId, options) {
20355
- const fileSize = (0, import_node_fs6.statSync)(options.file).size;
20407
+ const fileSize = (0, import_node_fs7.statSync)(options.file).size;
20356
20408
  const kind = validateHostedAppFile(options.file, fileSize);
20357
20409
  const conversationId = options.conversationId?.trim();
20358
20410
  if (conversationId && options.projectId?.trim()) throw new Error("--project-id cannot be used with --conversation-id");
20359
20411
  const resolvedConversationId = conversationId || await createBlankTask(creds, spaceId, options.projectId?.trim());
20360
- const content = (0, import_node_fs6.readFileSync)(options.file);
20412
+ const content = (0, import_node_fs7.readFileSync)(options.file);
20361
20413
  const upload = await uploadTaskAttachmentBytes(creds, {
20362
20414
  conversationId: resolvedConversationId,
20363
20415
  fileName: (0, import_node_path4.basename)(options.file),
@@ -20745,8 +20797,8 @@ var fs6 = __toESM(require("fs"));
20745
20797
  var path6 = __toESM(require("path"));
20746
20798
  var UNKNOWN_VERSION = "0.0.0";
20747
20799
  function injectedVersion() {
20748
- if ("0.1.28".length > 0) {
20749
- return "0.1.28";
20800
+ if ("0.1.29".length > 0) {
20801
+ return "0.1.29";
20750
20802
  }
20751
20803
  return null;
20752
20804
  }
@@ -21482,8 +21534,8 @@ function applyRememberRequest(message, authorized) {
21482
21534
  }
21483
21535
  async function performAction(message, scope, options) {
21484
21536
  const { command } = message;
21485
- const resolve4 = (input) => {
21486
- const check = authorizeTarget(scope, input);
21537
+ const resolve4 = (input2) => {
21538
+ const check = authorizeTarget(scope, input2);
21487
21539
  if (!check.ok) throw Object.assign(new Error(check.message), { code: check.code });
21488
21540
  return check.resolved;
21489
21541
  };
@@ -22521,6 +22573,18 @@ function isCliCommandAllowed(raw, groupName, subcommand) {
22521
22573
  if (subcommand && PUBLIC_MODEL_COMMANDS.has(subcommand)) return true;
22522
22574
  return allowed.get("model") === "all" || subcommand === "run" && allowed.get("model run") === "all";
22523
22575
  }
22576
+ if (groupName === "data" || groupName === "mail") {
22577
+ const entries = raw === void 0 ? process.env.KOLLAB_ALLOWED_CLI_COMMANDS : raw;
22578
+ let scopes = [];
22579
+ try {
22580
+ const parsed = JSON.parse(entries || "[]");
22581
+ if (Array.isArray(parsed) && parsed.every((s) => typeof s === "string")) scopes = parsed;
22582
+ } catch {
22583
+ return false;
22584
+ }
22585
+ const action = groupName === "data" ? ["collections", "list", "get", "changes"].includes(subcommand ?? "") ? "read" : subcommand === "configure" ? "manage" : "write" : subcommand === "send" ? "send" : ["mailbox", "recipient"].includes(subcommand ?? "") ? "manage" : "read";
22586
+ return scopes.includes(`${groupName}:${action}`);
22587
+ }
22524
22588
  const permission = allowed.get(groupName);
22525
22589
  if (!permission) return false;
22526
22590
  if (groupName !== "app" || permission === "all") return true;
@@ -22545,6 +22609,10 @@ function enforceCliCommandRestrictions(program2) {
22545
22609
  for (const cmd of program2.commands) {
22546
22610
  const groupName = cmd.name();
22547
22611
  if (UNRESTRICTED_COMMANDS.has(groupName)) continue;
22612
+ if (groupName === "data" || groupName === "mail") {
22613
+ for (const sub of cmd.commands) if (!isCliCommandAllowed(void 0, groupName, sub.name())) blockCommand(sub, `${groupName} ${sub.name()}`);
22614
+ continue;
22615
+ }
22548
22616
  if (groupName === "model") {
22549
22617
  for (const sub of cmd.commands) {
22550
22618
  if (!isCliCommandAllowed(void 0, "model", sub.name())) blockCommand(sub, `model ${sub.name()}`);
@@ -22614,6 +22682,7 @@ registerWorkspaceCommands(program);
22614
22682
  registerImagineCommands(program);
22615
22683
  registerUserCommands(program);
22616
22684
  registerHostedAppCommands(program);
22685
+ registerSitePlatformCommands(program);
22617
22686
  registerBrowserCommands(program);
22618
22687
  registerInviteCommands(program);
22619
22688
  registerModelCommands(program);