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 +183 -114
- package/dist/kollab-sidecar.cjs +444 -374
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12238,10 +12238,10 @@ function parseJsonErrorBody(raw) {
|
|
|
12238
12238
|
return void 0;
|
|
12239
12239
|
}
|
|
12240
12240
|
}
|
|
12241
|
-
function buildCreditReservedHint(
|
|
12242
|
-
const 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 =
|
|
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,
|
|
14178
|
+
function buildAskRequestBody(spaceId, input2) {
|
|
14179
14179
|
const qaQueryOption = {};
|
|
14180
|
-
if (
|
|
14181
|
-
qaQueryOption.knowledgeBaseIds = [
|
|
14180
|
+
if (input2.projectId) {
|
|
14181
|
+
qaQueryOption.knowledgeBaseIds = [input2.projectId];
|
|
14182
14182
|
}
|
|
14183
|
-
if (
|
|
14184
|
-
qaQueryOption.fileIds =
|
|
14183
|
+
if (input2.fileIds && input2.fileIds.length > 0) {
|
|
14184
|
+
qaQueryOption.fileIds = input2.fileIds;
|
|
14185
14185
|
}
|
|
14186
14186
|
const body = {
|
|
14187
|
-
question:
|
|
14188
|
-
message:
|
|
14187
|
+
question: input2.question,
|
|
14188
|
+
message: input2.question,
|
|
14189
14189
|
spaceId,
|
|
14190
|
-
conversationId:
|
|
14190
|
+
conversationId: input2.conversationId ?? "",
|
|
14191
14191
|
qaQueryOption,
|
|
14192
|
-
agent_id:
|
|
14193
|
-
agent_mentioned: hasKollabAgentMention(
|
|
14192
|
+
agent_id: input2.agentId ?? "default",
|
|
14193
|
+
agent_mentioned: hasKollabAgentMention(input2.question)
|
|
14194
14194
|
};
|
|
14195
|
-
if (
|
|
14196
|
-
body.projectId =
|
|
14195
|
+
if (input2.projectId) {
|
|
14196
|
+
body.projectId = input2.projectId;
|
|
14197
14197
|
}
|
|
14198
|
-
if (
|
|
14199
|
-
body.model_tier =
|
|
14198
|
+
if (input2.modelTier) {
|
|
14199
|
+
body.model_tier = input2.modelTier;
|
|
14200
14200
|
}
|
|
14201
|
-
if (
|
|
14202
|
-
body.byok_credential_id =
|
|
14201
|
+
if (input2.byokCredentialId) {
|
|
14202
|
+
body.byok_credential_id = input2.byokCredentialId;
|
|
14203
14203
|
}
|
|
14204
|
-
if (
|
|
14205
|
-
body.mcp_server_ids =
|
|
14204
|
+
if (input2.mcpServerIds && input2.mcpServerIds.length > 0) {
|
|
14205
|
+
body.mcp_server_ids = input2.mcpServerIds;
|
|
14206
14206
|
}
|
|
14207
|
-
if (
|
|
14208
|
-
body.uploaded_file_keys =
|
|
14207
|
+
if (input2.uploadedFileKeys && input2.uploadedFileKeys.length > 0) {
|
|
14208
|
+
body.uploaded_file_keys = input2.uploadedFileKeys;
|
|
14209
14209
|
}
|
|
14210
|
-
if (Array.isArray(
|
|
14211
|
-
body.attachments =
|
|
14210
|
+
if (Array.isArray(input2.attachments) && input2.attachments.length > 0) {
|
|
14211
|
+
body.attachments = input2.attachments;
|
|
14212
14212
|
}
|
|
14213
|
-
if (
|
|
14214
|
-
body.quotedMessageId =
|
|
14213
|
+
if (input2.quotedMessageId) {
|
|
14214
|
+
body.quotedMessageId = input2.quotedMessageId;
|
|
14215
14215
|
}
|
|
14216
|
-
if (
|
|
14216
|
+
if (input2.remixShareToken) {
|
|
14217
14217
|
body.remix_source = {
|
|
14218
14218
|
source_type: "share",
|
|
14219
|
-
share_token:
|
|
14220
|
-
...
|
|
14219
|
+
share_token: input2.remixShareToken,
|
|
14220
|
+
...input2.remixSourceTaskTitle ? { source_task_title: input2.remixSourceTaskTitle } : {}
|
|
14221
14221
|
};
|
|
14222
14222
|
}
|
|
14223
|
-
if (
|
|
14224
|
-
body.composer_mode =
|
|
14223
|
+
if (input2.composerMode) {
|
|
14224
|
+
body.composer_mode = input2.composerMode;
|
|
14225
14225
|
}
|
|
14226
|
-
if (
|
|
14227
|
-
body.composer_mode_options =
|
|
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(
|
|
14231
|
+
function buildAnswerQuestionRequestBody(input2) {
|
|
14232
14232
|
return {
|
|
14233
|
-
conversationId:
|
|
14234
|
-
tool_use_id:
|
|
14235
|
-
answers:
|
|
14236
|
-
agent_id:
|
|
14237
|
-
...
|
|
14238
|
-
...
|
|
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,
|
|
14683
|
-
if (!
|
|
14682
|
+
async function uploadTaskAttachmentBytes(creds, input2) {
|
|
14683
|
+
if (!input2.conversationId.trim()) {
|
|
14684
14684
|
throw new Error("conversationId is required");
|
|
14685
14685
|
}
|
|
14686
|
-
if (
|
|
14686
|
+
if (input2.content.byteLength > MAX_FILE_BYTES2) {
|
|
14687
14687
|
throw new Error(
|
|
14688
|
-
`File exceeds the 500 MB upload limit (${
|
|
14688
|
+
`File exceeds the 500 MB upload limit (${input2.content.byteLength} bytes): ${input2.fileName}`
|
|
14689
14689
|
);
|
|
14690
14690
|
}
|
|
14691
|
-
const fallbackMimeType =
|
|
14691
|
+
const fallbackMimeType = input2.contentType || mimeFromPath2(input2.fileName);
|
|
14692
14692
|
const uploadUrlResult = await api(creds, "POST", "/skills/chat/upload-url", {
|
|
14693
|
-
conversation_id:
|
|
14694
|
-
file_name:
|
|
14695
|
-
file_size:
|
|
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 ||
|
|
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:
|
|
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/${
|
|
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:
|
|
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:
|
|
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:
|
|
14764
|
+
size: input2.content.byteLength,
|
|
14765
14765
|
mime: resolvedMimeType,
|
|
14766
|
-
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 ${
|
|
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
|
|
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
|
-
|
|
14893
|
+
input2,
|
|
14894
14894
|
resolvedQuestion
|
|
14895
14895
|
);
|
|
14896
14896
|
const result = await runChatTurn(creds, {
|
|
14897
14897
|
path: "/skills/chat/stream",
|
|
14898
|
-
body: buildAskRequestBody(spaceId,
|
|
14899
|
-
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,
|
|
14921
|
-
if (!shouldMaterializeLargeQuestion(
|
|
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
|
-
|
|
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(
|
|
14932
|
+
content: new TextEncoder().encode(input2.question),
|
|
14933
14933
|
contentType: "text/plain;charset=utf-8"
|
|
14934
14934
|
});
|
|
14935
|
-
|
|
14936
|
-
|
|
14937
|
-
|
|
14938
|
-
...
|
|
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
|
-
|
|
14942
|
-
...normalizeAttachmentArray(
|
|
14941
|
+
input2.attachments = [
|
|
14942
|
+
...normalizeAttachmentArray(input2.attachments),
|
|
14943
14943
|
...uploaded.attachments
|
|
14944
14944
|
];
|
|
14945
14945
|
}
|
|
14946
|
-
async function ensureConversationForLargeQuestion(creds, spaceId,
|
|
14947
|
-
const existingConversationId =
|
|
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,
|
|
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,
|
|
14971
|
+
function buildLargeQuestionConversationPayload(spaceId, input2) {
|
|
14972
14972
|
return {
|
|
14973
14973
|
question: "",
|
|
14974
14974
|
spaceId,
|
|
14975
|
-
...
|
|
14976
|
-
...
|
|
14977
|
-
...
|
|
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
|
|
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(
|
|
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,
|
|
15346
|
-
let conversationId =
|
|
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
|
-
|
|
15352
|
-
|
|
15353
|
-
|
|
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:
|
|
15374
|
+
question: input2.question,
|
|
15375
15375
|
conversationId,
|
|
15376
|
-
projectId:
|
|
15377
|
-
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() +
|
|
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 &&
|
|
15404
|
-
await sleep4(
|
|
15403
|
+
if (sawGenerating && input2.relayAfterMs > 0) {
|
|
15404
|
+
await sleep4(input2.relayAfterMs);
|
|
15405
15405
|
}
|
|
15406
|
-
const relayCount = Math.max(1,
|
|
15407
|
-
const relayIntervalMs =
|
|
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 = `${
|
|
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
|
-
|
|
15424
|
-
|
|
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,
|
|
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 =
|
|
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(
|
|
17079
|
+
function hasUnbalancedQuotes(input2) {
|
|
17080
17080
|
let quote = null;
|
|
17081
|
-
for (let i = 0; i <
|
|
17082
|
-
const ch =
|
|
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(
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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.
|
|
20749
|
-
return "0.1.
|
|
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 = (
|
|
21486
|
-
const check = authorizeTarget(scope,
|
|
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);
|