@doist/automations-cli 1.22.1 → 1.22.3
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
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
collectSkillStatus,
|
|
8
8
|
getInstaller,
|
|
9
9
|
updateAllInstalledSkills
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DECO7WSK.js";
|
|
11
11
|
|
|
12
12
|
// ../../node_modules/ajv/dist/compile/codegen/code.js
|
|
13
13
|
var require_code = __commonJS({
|
|
@@ -6899,7 +6899,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6899
6899
|
// package.json
|
|
6900
6900
|
var package_default = {
|
|
6901
6901
|
name: "@doist/automations-cli",
|
|
6902
|
-
version: "1.22.
|
|
6902
|
+
version: "1.22.3",
|
|
6903
6903
|
description: "Command-line client for Todoist Automations",
|
|
6904
6904
|
type: "module",
|
|
6905
6905
|
bin: {
|
|
@@ -6933,7 +6933,7 @@ var package_default = {
|
|
|
6933
6933
|
build: "node scripts/build.mjs && node scripts/refresh-skills.mjs",
|
|
6934
6934
|
dev: "node scripts/build.mjs --watch",
|
|
6935
6935
|
"type-check": "tsc -p tsconfig.test.json --noEmit",
|
|
6936
|
-
test: "vitest run",
|
|
6936
|
+
test: "vitest run && node --test '../../release/*.test.mjs'",
|
|
6937
6937
|
check: "oxfmt src scripts --check && oxlint src scripts && npm run check:skill-sync",
|
|
6938
6938
|
"check:fix": "oxfmt src scripts && oxlint src scripts --fix",
|
|
6939
6939
|
"sync:skill": "node scripts/sync-skill.mjs",
|
|
@@ -6957,7 +6957,6 @@ var package_default = {
|
|
|
6957
6957
|
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
6958
6958
|
esbuild: "0.28.2",
|
|
6959
6959
|
"semantic-release": "25.0.9",
|
|
6960
|
-
"semantic-release-monorepo": "8.0.2",
|
|
6961
6960
|
typescript: "6.0.3",
|
|
6962
6961
|
vitest: "5.0.5"
|
|
6963
6962
|
},
|
|
@@ -34696,6 +34695,491 @@ function addWorkspaceScopeOptions(command) {
|
|
|
34696
34695
|
).option("--personal", "Act on your personal space, ignoring any pinned workspace");
|
|
34697
34696
|
}
|
|
34698
34697
|
|
|
34698
|
+
// ../../packages/sdk/dist/esm/chat-turn/connection-requirements.js
|
|
34699
|
+
var CONNECTION_LOOKUP_CONCURRENCY = 4;
|
|
34700
|
+
function deduplicateConnectionRequirements(requirements) {
|
|
34701
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34702
|
+
return requirements.filter((requirement) => {
|
|
34703
|
+
const key = JSON.stringify([requirement.connectorId, requirement.connectionType]);
|
|
34704
|
+
if (seen.has(key))
|
|
34705
|
+
return false;
|
|
34706
|
+
seen.add(key);
|
|
34707
|
+
return true;
|
|
34708
|
+
});
|
|
34709
|
+
}
|
|
34710
|
+
async function loadConnectionRequirements(connections, requirements, options) {
|
|
34711
|
+
return mapWithConcurrency(deduplicateConnectionRequirements(requirements), CONNECTION_LOOKUP_CONCURRENCY, async (requirement) => {
|
|
34712
|
+
const response = await connections.list({
|
|
34713
|
+
connectorId: requirement.connectorId,
|
|
34714
|
+
capability: requirement.connectionType,
|
|
34715
|
+
status: "authorized"
|
|
34716
|
+
}, options);
|
|
34717
|
+
return {
|
|
34718
|
+
...requirement,
|
|
34719
|
+
availableConnections: response.connections.map((connection) => ({
|
|
34720
|
+
id: connection.id,
|
|
34721
|
+
label: connection.accountDisplayLabel ?? connection.name ?? connection.id
|
|
34722
|
+
}))
|
|
34723
|
+
};
|
|
34724
|
+
});
|
|
34725
|
+
}
|
|
34726
|
+
async function mapWithConcurrency(items, concurrency, map2) {
|
|
34727
|
+
const results = new Array(items.length);
|
|
34728
|
+
let next = 0;
|
|
34729
|
+
const workers = Array.from({ length: Math.min(concurrency, items.length) }, async () => {
|
|
34730
|
+
while (next < items.length) {
|
|
34731
|
+
const index = next;
|
|
34732
|
+
next += 1;
|
|
34733
|
+
results[index] = await map2(items[index]);
|
|
34734
|
+
}
|
|
34735
|
+
});
|
|
34736
|
+
await Promise.all(workers);
|
|
34737
|
+
return results;
|
|
34738
|
+
}
|
|
34739
|
+
|
|
34740
|
+
// ../../packages/sdk/dist/esm/chat-turn/connection-setup.js
|
|
34741
|
+
async function startConnectionSetup(connections, request2, options) {
|
|
34742
|
+
const created = await connections.create({
|
|
34743
|
+
connectorId: request2.connectorId,
|
|
34744
|
+
capability: request2.capability,
|
|
34745
|
+
...request2.automationIds?.length ? { body: { automationIds: [...request2.automationIds] } } : {}
|
|
34746
|
+
}, options);
|
|
34747
|
+
return { connectionId: created.connectionId, setup: created.setup, resumed: false };
|
|
34748
|
+
}
|
|
34749
|
+
function summarizeConnectionSetup(setup) {
|
|
34750
|
+
if (setup?.kind === "oauth") {
|
|
34751
|
+
return { setupKind: "oauth", authorizationUrl: setup.authorizationUrl };
|
|
34752
|
+
}
|
|
34753
|
+
if (setup?.kind === "managed") {
|
|
34754
|
+
return {
|
|
34755
|
+
setupKind: "managed",
|
|
34756
|
+
instructions: setup.instructions,
|
|
34757
|
+
code: setup.code,
|
|
34758
|
+
deepLinkUrl: setup.deepLinkUrl,
|
|
34759
|
+
expiresAt: setup.expiresAt
|
|
34760
|
+
};
|
|
34761
|
+
}
|
|
34762
|
+
return { setupKind: "none" };
|
|
34763
|
+
}
|
|
34764
|
+
function getConnectionSetupUrl(setup) {
|
|
34765
|
+
if (setup?.kind === "oauth")
|
|
34766
|
+
return setup.authorizationUrl;
|
|
34767
|
+
if (setup?.kind === "managed")
|
|
34768
|
+
return setup.deepLinkUrl;
|
|
34769
|
+
return null;
|
|
34770
|
+
}
|
|
34771
|
+
|
|
34772
|
+
// ../../packages/core/dist/esm/chat-tools/client-tool-result.js
|
|
34773
|
+
var clientToolContinuationPartSchema = external_exports.discriminatedUnion("type", [
|
|
34774
|
+
toolPromptEnablePushResultSchema.omit({ input: true }).strict(),
|
|
34775
|
+
toolSelectConnectionsResultSchema.omit({ input: true }).strict()
|
|
34776
|
+
]);
|
|
34777
|
+
|
|
34778
|
+
// ../../packages/core/dist/esm/chat-tools/update-memory.js
|
|
34779
|
+
var UpdateMemoryInputSchema = external_exports.object({
|
|
34780
|
+
append: external_exports.string().min(1).optional(),
|
|
34781
|
+
replace: external_exports.object({
|
|
34782
|
+
old: external_exports.string().min(1),
|
|
34783
|
+
new: external_exports.string()
|
|
34784
|
+
}).optional()
|
|
34785
|
+
});
|
|
34786
|
+
var UpdateMemoryOutputSchema = external_exports.object({
|
|
34787
|
+
memory: external_exports.string().nullable(),
|
|
34788
|
+
// What the memory held before this write — the chat UI's Undo restores it.
|
|
34789
|
+
previousMemory: external_exports.string().nullable()
|
|
34790
|
+
});
|
|
34791
|
+
var toolUpdateMemorySchema = external_exports.object({
|
|
34792
|
+
type: external_exports.literal("tool-update-memory"),
|
|
34793
|
+
toolCallId: external_exports.string().min(1),
|
|
34794
|
+
state: external_exports.literal("input-available"),
|
|
34795
|
+
input: UpdateMemoryInputSchema
|
|
34796
|
+
});
|
|
34797
|
+
var toolUpdateMemoryResultSchema = external_exports.object({
|
|
34798
|
+
type: external_exports.literal("tool-update-memory"),
|
|
34799
|
+
toolCallId: external_exports.string().min(1),
|
|
34800
|
+
state: external_exports.literal("output-available"),
|
|
34801
|
+
input: UpdateMemoryInputSchema,
|
|
34802
|
+
output: UpdateMemoryOutputSchema
|
|
34803
|
+
});
|
|
34804
|
+
|
|
34805
|
+
// ../../packages/sdk/dist/esm/chat-turn/messages.js
|
|
34806
|
+
var persistedToolPartSchema = external_exports.object({
|
|
34807
|
+
type: external_exports.string().trim().min(6).refine((type) => type.startsWith("tool-")),
|
|
34808
|
+
toolCallId: external_exports.string().trim().min(1),
|
|
34809
|
+
state: external_exports.enum(["input-streaming", "input-available", "output-available", "output-error"])
|
|
34810
|
+
}).passthrough();
|
|
34811
|
+
function createUserMessage(text2) {
|
|
34812
|
+
return {
|
|
34813
|
+
id: globalThis.crypto.randomUUID(),
|
|
34814
|
+
role: "user",
|
|
34815
|
+
parts: [{ type: "text", text: text2 }]
|
|
34816
|
+
};
|
|
34817
|
+
}
|
|
34818
|
+
function toUiMessage(message) {
|
|
34819
|
+
if (message.role !== "user" && message.role !== "assistant" && message.role !== "system") {
|
|
34820
|
+
throw new Error(`Unsupported persisted chat role: ${message.role}`);
|
|
34821
|
+
}
|
|
34822
|
+
if (!Array.isArray(message.parts)) {
|
|
34823
|
+
throw new Error(`Persisted chat message ${message.messageId} has invalid parts.`);
|
|
34824
|
+
}
|
|
34825
|
+
return {
|
|
34826
|
+
id: message.messageId,
|
|
34827
|
+
role: message.role,
|
|
34828
|
+
parts: normalizePersistedMessageParts(message.parts)
|
|
34829
|
+
};
|
|
34830
|
+
}
|
|
34831
|
+
function normalizePersistedMessageParts(parts) {
|
|
34832
|
+
return parts.filter((part) => isTextPart(part) || isStepStartPart(part) || isReasoningPart(part) || persistedToolPartSchema.safeParse(part).success);
|
|
34833
|
+
}
|
|
34834
|
+
function isTextPart(part) {
|
|
34835
|
+
if (typeof part !== "object" || part === null) {
|
|
34836
|
+
return false;
|
|
34837
|
+
}
|
|
34838
|
+
const candidate = part;
|
|
34839
|
+
return candidate.type === "text" && typeof candidate.text === "string";
|
|
34840
|
+
}
|
|
34841
|
+
function isStepStartPart(part) {
|
|
34842
|
+
if (typeof part !== "object" || part === null) {
|
|
34843
|
+
return false;
|
|
34844
|
+
}
|
|
34845
|
+
return part.type === "step-start";
|
|
34846
|
+
}
|
|
34847
|
+
function isReasoningPart(part) {
|
|
34848
|
+
if (typeof part !== "object" || part === null) {
|
|
34849
|
+
return false;
|
|
34850
|
+
}
|
|
34851
|
+
const candidate = part;
|
|
34852
|
+
return candidate.type === "reasoning" && typeof candidate.text === "string" && (candidate.state === void 0 || candidate.state === "streaming" || candidate.state === "done");
|
|
34853
|
+
}
|
|
34854
|
+
function getVisibleText(message) {
|
|
34855
|
+
return message.parts.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
34856
|
+
}
|
|
34857
|
+
function getPendingClientAction(message) {
|
|
34858
|
+
for (let index = message.parts.length - 1; index >= 0; index -= 1) {
|
|
34859
|
+
const part = message.parts[index];
|
|
34860
|
+
if (isSelectConnections(part)) {
|
|
34861
|
+
return {
|
|
34862
|
+
kind: "select_connections",
|
|
34863
|
+
message,
|
|
34864
|
+
toolCallId: part.toolCallId,
|
|
34865
|
+
draftId: part.input.draftId,
|
|
34866
|
+
connections: part.input.connections
|
|
34867
|
+
};
|
|
34868
|
+
}
|
|
34869
|
+
if (isPromptEnablePush(part)) {
|
|
34870
|
+
return {
|
|
34871
|
+
kind: "enable_push",
|
|
34872
|
+
message,
|
|
34873
|
+
toolCallId: part.toolCallId,
|
|
34874
|
+
draftId: part.input.draftId
|
|
34875
|
+
};
|
|
34876
|
+
}
|
|
34877
|
+
}
|
|
34878
|
+
return null;
|
|
34879
|
+
}
|
|
34880
|
+
function getPendingActionFromMessages(messages) {
|
|
34881
|
+
const latestMessage = messages.at(-1);
|
|
34882
|
+
if (!latestMessage || latestMessage.role !== "assistant")
|
|
34883
|
+
return null;
|
|
34884
|
+
return getPendingClientAction(toUiMessage(latestMessage));
|
|
34885
|
+
}
|
|
34886
|
+
function getPublishedAutomationId(message) {
|
|
34887
|
+
for (let index = message.parts.length - 1; index >= 0; index -= 1) {
|
|
34888
|
+
const part = message.parts[index];
|
|
34889
|
+
if (isPublishDraftResult(part) && part.output.success) {
|
|
34890
|
+
return part.output.automationId;
|
|
34891
|
+
}
|
|
34892
|
+
}
|
|
34893
|
+
return void 0;
|
|
34894
|
+
}
|
|
34895
|
+
function createEnablePushContinuation(action, output2) {
|
|
34896
|
+
return {
|
|
34897
|
+
id: action.message.id,
|
|
34898
|
+
role: "assistant",
|
|
34899
|
+
parts: [
|
|
34900
|
+
{
|
|
34901
|
+
type: "tool-prompt-enable-push-notifications",
|
|
34902
|
+
toolCallId: action.toolCallId,
|
|
34903
|
+
state: "output-available",
|
|
34904
|
+
output: output2
|
|
34905
|
+
}
|
|
34906
|
+
]
|
|
34907
|
+
};
|
|
34908
|
+
}
|
|
34909
|
+
function createSelectConnectionsContinuation(action, output2) {
|
|
34910
|
+
return {
|
|
34911
|
+
id: action.message.id,
|
|
34912
|
+
role: "assistant",
|
|
34913
|
+
parts: [
|
|
34914
|
+
{
|
|
34915
|
+
type: "tool-select-connections",
|
|
34916
|
+
toolCallId: action.toolCallId,
|
|
34917
|
+
state: "output-available",
|
|
34918
|
+
output: output2
|
|
34919
|
+
}
|
|
34920
|
+
]
|
|
34921
|
+
};
|
|
34922
|
+
}
|
|
34923
|
+
|
|
34924
|
+
// ../../packages/sdk/dist/esm/chat-turn/types.js
|
|
34925
|
+
var ChatTurnInputError = class extends Error {
|
|
34926
|
+
code;
|
|
34927
|
+
constructor(code, message) {
|
|
34928
|
+
super(message);
|
|
34929
|
+
this.name = "ChatTurnInputError";
|
|
34930
|
+
this.code = code;
|
|
34931
|
+
}
|
|
34932
|
+
};
|
|
34933
|
+
|
|
34934
|
+
// ../../packages/sdk/dist/esm/chat-turn/run-conversation-turn.js
|
|
34935
|
+
async function runConversationTurn(options) {
|
|
34936
|
+
const { api, transport, conversationId, signal } = options;
|
|
34937
|
+
const workspaceId = options.workspaceId ?? null;
|
|
34938
|
+
const requestOptions = { signal };
|
|
34939
|
+
const pending = await readPendingAction(options);
|
|
34940
|
+
let nextMessage;
|
|
34941
|
+
if (pending?.kind === "enable_push") {
|
|
34942
|
+
if ("message" in options.input || options.input.selections.length > 0) {
|
|
34943
|
+
throw new ChatTurnInputError("awaiting_push", "The conversation is waiting for the push notification prompt to be answered.");
|
|
34944
|
+
}
|
|
34945
|
+
nextMessage = await answerEnablePush(options, pending);
|
|
34946
|
+
} else if ("message" in options.input) {
|
|
34947
|
+
if (pending?.kind === "select_connections") {
|
|
34948
|
+
throw new ChatTurnInputError("awaiting_selection", "The conversation is waiting for connection selection.");
|
|
34949
|
+
}
|
|
34950
|
+
nextMessage = createUserMessage(options.input.message);
|
|
34951
|
+
} else {
|
|
34952
|
+
const selections = options.input.selections;
|
|
34953
|
+
if (pending?.kind !== "select_connections") {
|
|
34954
|
+
throw new ChatTurnInputError(selections.length > 0 ? "not_awaiting_selection" : "input_required", selections.length > 0 ? "The conversation is not waiting for connection selection." : "A message is required to continue.");
|
|
34955
|
+
}
|
|
34956
|
+
const resolution = await resolveSelectConnections(options, pending, selections);
|
|
34957
|
+
if (resolution.kind === "required") {
|
|
34958
|
+
return actionRequired(conversationId, getVisibleText(pending.message), resolution.pendingAction);
|
|
34959
|
+
}
|
|
34960
|
+
nextMessage = resolution.continuation;
|
|
34961
|
+
}
|
|
34962
|
+
while (true) {
|
|
34963
|
+
const response = await transport.streamTurn({
|
|
34964
|
+
conversationId,
|
|
34965
|
+
workspaceId,
|
|
34966
|
+
message: nextMessage,
|
|
34967
|
+
signal,
|
|
34968
|
+
onText: options.onText,
|
|
34969
|
+
onToolActivity: options.onToolActivity
|
|
34970
|
+
});
|
|
34971
|
+
const assistantText = getVisibleText(response);
|
|
34972
|
+
const automationId = getPublishedAutomationId(response);
|
|
34973
|
+
if (automationId) {
|
|
34974
|
+
options.onPublished?.(automationId);
|
|
34975
|
+
const archive = await archiveConversation(api, conversationId, requestOptions);
|
|
34976
|
+
return {
|
|
34977
|
+
conversationId,
|
|
34978
|
+
outcome: "published",
|
|
34979
|
+
assistantText,
|
|
34980
|
+
automationId,
|
|
34981
|
+
...archive
|
|
34982
|
+
};
|
|
34983
|
+
}
|
|
34984
|
+
const responseAction = getPendingClientAction(response);
|
|
34985
|
+
if (responseAction?.kind === "select_connections") {
|
|
34986
|
+
const resolution = await resolveSelectConnections(options, responseAction, []);
|
|
34987
|
+
if (resolution.kind === "resolved") {
|
|
34988
|
+
nextMessage = resolution.continuation;
|
|
34989
|
+
continue;
|
|
34990
|
+
}
|
|
34991
|
+
return actionRequired(conversationId, assistantText, resolution.pendingAction);
|
|
34992
|
+
}
|
|
34993
|
+
if (responseAction?.kind === "enable_push") {
|
|
34994
|
+
return actionRequired(conversationId, assistantText, {
|
|
34995
|
+
kind: "enable_push",
|
|
34996
|
+
toolCallId: responseAction.toolCallId,
|
|
34997
|
+
draftId: responseAction.draftId
|
|
34998
|
+
});
|
|
34999
|
+
}
|
|
35000
|
+
return { conversationId, outcome: "awaiting_input", assistantText };
|
|
35001
|
+
}
|
|
35002
|
+
}
|
|
35003
|
+
async function answerEnablePush(options, action) {
|
|
35004
|
+
const { subscriptions } = await options.api.notifications.push.list({
|
|
35005
|
+
signal: options.signal
|
|
35006
|
+
});
|
|
35007
|
+
const deviceCount = subscriptions.length;
|
|
35008
|
+
return createEnablePushContinuation(action, {
|
|
35009
|
+
enabled: deviceCount > 0,
|
|
35010
|
+
deviceCount,
|
|
35011
|
+
message: deviceCount > 0 ? `Push notifications are enabled on ${deviceCount} device${deviceCount === 1 ? "" : "s"}.` : "The user has not enabled push notifications."
|
|
35012
|
+
});
|
|
35013
|
+
}
|
|
35014
|
+
async function readPendingAction(options) {
|
|
35015
|
+
if (options.pendingAction !== void 0)
|
|
35016
|
+
return options.pendingAction;
|
|
35017
|
+
const messages = await options.api.chat.getMessages(options.conversationId, {
|
|
35018
|
+
signal: options.signal
|
|
35019
|
+
});
|
|
35020
|
+
return getPendingActionFromMessages(messages);
|
|
35021
|
+
}
|
|
35022
|
+
function actionRequired(conversationId, assistantText, pendingAction) {
|
|
35023
|
+
return { conversationId, outcome: "action_required", assistantText, pendingAction };
|
|
35024
|
+
}
|
|
35025
|
+
async function archiveConversation(api, conversationId, requestOptions) {
|
|
35026
|
+
try {
|
|
35027
|
+
const conversation = await api.chat.updateConversation(conversationId, { isArchived: true }, requestOptions);
|
|
35028
|
+
if (!conversation.isArchived) {
|
|
35029
|
+
throw new Error("The Automations API returned an active conversation.");
|
|
35030
|
+
}
|
|
35031
|
+
return { conversationArchived: true };
|
|
35032
|
+
} catch (error62) {
|
|
35033
|
+
return {
|
|
35034
|
+
conversationArchived: false,
|
|
35035
|
+
conversationArchiveError: error62 instanceof Error ? error62.message : String(error62)
|
|
35036
|
+
};
|
|
35037
|
+
}
|
|
35038
|
+
}
|
|
35039
|
+
async function resolveSelectConnections(options, action, selections) {
|
|
35040
|
+
const { api, signal } = options;
|
|
35041
|
+
const requestOptions = { signal };
|
|
35042
|
+
const requirements = await loadConnectionRequirements(api.connections, action.connections, requestOptions);
|
|
35043
|
+
assertSelectionsUnambiguous(requirements, selections);
|
|
35044
|
+
const resolved = [];
|
|
35045
|
+
for (const requirement of requirements) {
|
|
35046
|
+
const explicit = selections.find((selection) => selection.connectorId === requirement.connectorId && (!selection.connectionType || selection.connectionType === requirement.connectionType));
|
|
35047
|
+
let connectionId = explicit?.connectionId;
|
|
35048
|
+
let setup;
|
|
35049
|
+
if (connectionId) {
|
|
35050
|
+
const exists = requirement.availableConnections.some((connection) => connection.id === connectionId);
|
|
35051
|
+
if (!exists) {
|
|
35052
|
+
throw new ChatTurnInputError("unknown_connection", `Connection ${connectionId} is not an authorized ${requirement.serviceName} connection.`);
|
|
35053
|
+
}
|
|
35054
|
+
} else if (requirement.availableConnections.length === 1) {
|
|
35055
|
+
connectionId = requirement.availableConnections[0]?.id;
|
|
35056
|
+
} else if (requirement.availableConnections.length > 1) {
|
|
35057
|
+
connectionId = await options.chooseConnection?.(requirement);
|
|
35058
|
+
} else if (options.authorizeConnection) {
|
|
35059
|
+
connectionId = await options.authorizeConnection(requirement);
|
|
35060
|
+
} else {
|
|
35061
|
+
setup = await startConnectionSetup(api.connections, { connectorId: requirement.connectorId, capability: requirement.connectionType }, requestOptions);
|
|
35062
|
+
}
|
|
35063
|
+
if (!connectionId) {
|
|
35064
|
+
return {
|
|
35065
|
+
kind: "required",
|
|
35066
|
+
pendingAction: {
|
|
35067
|
+
kind: "select_connections",
|
|
35068
|
+
toolCallId: action.toolCallId,
|
|
35069
|
+
draftId: action.draftId,
|
|
35070
|
+
requirements: requirements.map((item) => item === requirement && setup ? { ...item, setup } : item)
|
|
35071
|
+
}
|
|
35072
|
+
};
|
|
35073
|
+
}
|
|
35074
|
+
resolved.push({ requirement, connectionId });
|
|
35075
|
+
}
|
|
35076
|
+
const output2 = [];
|
|
35077
|
+
for (const item of resolved) {
|
|
35078
|
+
const body = {
|
|
35079
|
+
connectorId: item.requirement.connectorId,
|
|
35080
|
+
connectionType: item.requirement.connectionType,
|
|
35081
|
+
connectionId: item.connectionId
|
|
35082
|
+
};
|
|
35083
|
+
const workspaceId = options.workspaceId ?? null;
|
|
35084
|
+
if (workspaceId === null) {
|
|
35085
|
+
await api.automationDraftConnections.upsert(action.draftId, body, requestOptions);
|
|
35086
|
+
} else {
|
|
35087
|
+
await api.workspaceAutomationDraftConnections.upsert(workspaceId, action.draftId, body, requestOptions);
|
|
35088
|
+
}
|
|
35089
|
+
output2.push({ type: "success", ...body });
|
|
35090
|
+
}
|
|
35091
|
+
return { kind: "resolved", continuation: createSelectConnectionsContinuation(action, output2) };
|
|
35092
|
+
}
|
|
35093
|
+
function assertSelectionsUnambiguous(requirements, selections) {
|
|
35094
|
+
for (const selection of selections) {
|
|
35095
|
+
if (selection.connectionType)
|
|
35096
|
+
continue;
|
|
35097
|
+
const matchingTypes = new Set(requirements.filter((requirement) => requirement.connectorId === selection.connectorId).map((requirement) => requirement.connectionType));
|
|
35098
|
+
if (matchingTypes.size > 1) {
|
|
35099
|
+
throw new ChatTurnInputError("ambiguous_selection", `Connection selection for ${selection.connectorId} is ambiguous. Specify ${selection.connectorId}:mcp or ${selection.connectorId}:trigger.`);
|
|
35100
|
+
}
|
|
35101
|
+
}
|
|
35102
|
+
}
|
|
35103
|
+
|
|
35104
|
+
// ../../packages/sdk/dist/esm/chat-turn/transport.js
|
|
35105
|
+
import { DefaultChatTransport, readUIMessageStream } from "ai";
|
|
35106
|
+
var ChatTurnTransport = class {
|
|
35107
|
+
transport;
|
|
35108
|
+
constructor({ token, baseUrl, headers, fetch: fetch2 }) {
|
|
35109
|
+
const apiRoot = `${baseUrl.replace(/\/+$/, "")}/v1`;
|
|
35110
|
+
this.transport = new DefaultChatTransport({
|
|
35111
|
+
api: `${apiRoot}/chat`,
|
|
35112
|
+
headers: {
|
|
35113
|
+
Authorization: `Bearer ${token}`,
|
|
35114
|
+
...headers
|
|
35115
|
+
},
|
|
35116
|
+
credentials: "include",
|
|
35117
|
+
fetch: fetch2,
|
|
35118
|
+
prepareSendMessagesRequest({ messages, body, api }) {
|
|
35119
|
+
const { workspaceId, ...rest } = body ?? {};
|
|
35120
|
+
return {
|
|
35121
|
+
api: workspaceId ? `${apiRoot}/workspaces/${encodeURIComponent(workspaceId)}/chat` : api,
|
|
35122
|
+
body: {
|
|
35123
|
+
...rest,
|
|
35124
|
+
message: messages.at(-1)
|
|
35125
|
+
}
|
|
35126
|
+
};
|
|
35127
|
+
}
|
|
35128
|
+
});
|
|
35129
|
+
}
|
|
35130
|
+
/** Streams one server turn, reporting incremental text and deduplicated tool state changes. */
|
|
35131
|
+
async streamTurn({ conversationId, workspaceId = null, message, signal, onText, onToolActivity }) {
|
|
35132
|
+
const stream = await this.transport.sendMessages({
|
|
35133
|
+
trigger: "submit-message",
|
|
35134
|
+
chatId: conversationId,
|
|
35135
|
+
messageId: void 0,
|
|
35136
|
+
messages: [message],
|
|
35137
|
+
abortSignal: signal,
|
|
35138
|
+
body: { conversationId, workspaceId }
|
|
35139
|
+
});
|
|
35140
|
+
let finalMessage;
|
|
35141
|
+
let emittedText = "";
|
|
35142
|
+
const emittedToolStates = /* @__PURE__ */ new Set();
|
|
35143
|
+
for await (const currentMessage of readUIMessageStream({
|
|
35144
|
+
stream,
|
|
35145
|
+
terminateOnError: true
|
|
35146
|
+
})) {
|
|
35147
|
+
finalMessage = currentMessage;
|
|
35148
|
+
const visibleText = getVisibleText(currentMessage);
|
|
35149
|
+
if (visibleText.startsWith(emittedText)) {
|
|
35150
|
+
const delta = visibleText.slice(emittedText.length);
|
|
35151
|
+
if (delta)
|
|
35152
|
+
onText?.(delta);
|
|
35153
|
+
emittedText = visibleText;
|
|
35154
|
+
}
|
|
35155
|
+
for (const part of currentMessage.parts) {
|
|
35156
|
+
const activity = toToolActivity(part);
|
|
35157
|
+
if (!activity)
|
|
35158
|
+
continue;
|
|
35159
|
+
const key = `${activity.toolCallId}:${activity.state}`;
|
|
35160
|
+
if (emittedToolStates.has(key))
|
|
35161
|
+
continue;
|
|
35162
|
+
emittedToolStates.add(key);
|
|
35163
|
+
onToolActivity?.(activity);
|
|
35164
|
+
}
|
|
35165
|
+
}
|
|
35166
|
+
if (!finalMessage) {
|
|
35167
|
+
throw new Error("The Automations chat returned an empty response.");
|
|
35168
|
+
}
|
|
35169
|
+
return finalMessage;
|
|
35170
|
+
}
|
|
35171
|
+
};
|
|
35172
|
+
function toToolActivity(part) {
|
|
35173
|
+
if (!part.type.startsWith("tool-") || !("toolCallId" in part) || !("state" in part)) {
|
|
35174
|
+
return null;
|
|
35175
|
+
}
|
|
35176
|
+
return {
|
|
35177
|
+
tool: part.type.slice("tool-".length),
|
|
35178
|
+
toolCallId: String(part.toolCallId),
|
|
35179
|
+
state: String(part.state)
|
|
35180
|
+
};
|
|
35181
|
+
}
|
|
35182
|
+
|
|
34699
35183
|
// src/commands/read/format.ts
|
|
34700
35184
|
function formatAutomationList(page) {
|
|
34701
35185
|
if (page.data.length === 0) return "No automations found.";
|
|
@@ -34864,9 +35348,6 @@ function getMessageSummary(message) {
|
|
|
34864
35348
|
const partTypes = message.parts.filter(isRecord2).map((part) => typeof part.type === "string" ? part.type : "unknown");
|
|
34865
35349
|
return partTypes.length > 0 ? `[${partTypes.join(", ")}]` : "(no visible text)";
|
|
34866
35350
|
}
|
|
34867
|
-
function isTextPart(value) {
|
|
34868
|
-
return isRecord2(value) && value.type === "text" && typeof value.text === "string";
|
|
34869
|
-
}
|
|
34870
35351
|
function isRecord2(value) {
|
|
34871
35352
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34872
35353
|
}
|
|
@@ -35245,463 +35726,6 @@ function collectOption(value, previous) {
|
|
|
35245
35726
|
return [...previous, value];
|
|
35246
35727
|
}
|
|
35247
35728
|
|
|
35248
|
-
// ../../packages/sdk/dist/esm/chat-turn/connection-requirements.js
|
|
35249
|
-
var CONNECTION_LOOKUP_CONCURRENCY = 4;
|
|
35250
|
-
function deduplicateConnectionRequirements(requirements) {
|
|
35251
|
-
const seen = /* @__PURE__ */ new Set();
|
|
35252
|
-
return requirements.filter((requirement) => {
|
|
35253
|
-
const key = JSON.stringify([requirement.connectorId, requirement.connectionType]);
|
|
35254
|
-
if (seen.has(key))
|
|
35255
|
-
return false;
|
|
35256
|
-
seen.add(key);
|
|
35257
|
-
return true;
|
|
35258
|
-
});
|
|
35259
|
-
}
|
|
35260
|
-
async function loadConnectionRequirements(connections, requirements, options) {
|
|
35261
|
-
return mapWithConcurrency(deduplicateConnectionRequirements(requirements), CONNECTION_LOOKUP_CONCURRENCY, async (requirement) => {
|
|
35262
|
-
const response = await connections.list({
|
|
35263
|
-
connectorId: requirement.connectorId,
|
|
35264
|
-
capability: requirement.connectionType,
|
|
35265
|
-
status: "authorized"
|
|
35266
|
-
}, options);
|
|
35267
|
-
return {
|
|
35268
|
-
...requirement,
|
|
35269
|
-
availableConnections: response.connections.map((connection) => ({
|
|
35270
|
-
id: connection.id,
|
|
35271
|
-
label: connection.accountDisplayLabel ?? connection.name ?? connection.id
|
|
35272
|
-
}))
|
|
35273
|
-
};
|
|
35274
|
-
});
|
|
35275
|
-
}
|
|
35276
|
-
async function mapWithConcurrency(items, concurrency, map2) {
|
|
35277
|
-
const results = new Array(items.length);
|
|
35278
|
-
let next = 0;
|
|
35279
|
-
const workers = Array.from({ length: Math.min(concurrency, items.length) }, async () => {
|
|
35280
|
-
while (next < items.length) {
|
|
35281
|
-
const index = next;
|
|
35282
|
-
next += 1;
|
|
35283
|
-
results[index] = await map2(items[index]);
|
|
35284
|
-
}
|
|
35285
|
-
});
|
|
35286
|
-
await Promise.all(workers);
|
|
35287
|
-
return results;
|
|
35288
|
-
}
|
|
35289
|
-
|
|
35290
|
-
// ../../packages/sdk/dist/esm/chat-turn/connection-setup.js
|
|
35291
|
-
async function startConnectionSetup(connections, request2, options) {
|
|
35292
|
-
const created = await connections.create({
|
|
35293
|
-
connectorId: request2.connectorId,
|
|
35294
|
-
capability: request2.capability,
|
|
35295
|
-
...request2.automationIds?.length ? { body: { automationIds: [...request2.automationIds] } } : {}
|
|
35296
|
-
}, options);
|
|
35297
|
-
return { connectionId: created.connectionId, setup: created.setup, resumed: false };
|
|
35298
|
-
}
|
|
35299
|
-
function summarizeConnectionSetup(setup) {
|
|
35300
|
-
if (setup?.kind === "oauth") {
|
|
35301
|
-
return { setupKind: "oauth", authorizationUrl: setup.authorizationUrl };
|
|
35302
|
-
}
|
|
35303
|
-
if (setup?.kind === "managed") {
|
|
35304
|
-
return {
|
|
35305
|
-
setupKind: "managed",
|
|
35306
|
-
instructions: setup.instructions,
|
|
35307
|
-
code: setup.code,
|
|
35308
|
-
deepLinkUrl: setup.deepLinkUrl,
|
|
35309
|
-
expiresAt: setup.expiresAt
|
|
35310
|
-
};
|
|
35311
|
-
}
|
|
35312
|
-
return { setupKind: "none" };
|
|
35313
|
-
}
|
|
35314
|
-
function getConnectionSetupUrl(setup) {
|
|
35315
|
-
if (setup?.kind === "oauth")
|
|
35316
|
-
return setup.authorizationUrl;
|
|
35317
|
-
if (setup?.kind === "managed")
|
|
35318
|
-
return setup.deepLinkUrl;
|
|
35319
|
-
return null;
|
|
35320
|
-
}
|
|
35321
|
-
|
|
35322
|
-
// ../../packages/core/dist/esm/chat-tools/client-tool-result.js
|
|
35323
|
-
var clientToolContinuationPartSchema = external_exports.discriminatedUnion("type", [
|
|
35324
|
-
toolPromptEnablePushResultSchema.omit({ input: true }).strict(),
|
|
35325
|
-
toolSelectConnectionsResultSchema.omit({ input: true }).strict()
|
|
35326
|
-
]);
|
|
35327
|
-
|
|
35328
|
-
// ../../packages/core/dist/esm/chat-tools/update-memory.js
|
|
35329
|
-
var UpdateMemoryInputSchema = external_exports.object({
|
|
35330
|
-
append: external_exports.string().min(1).optional(),
|
|
35331
|
-
replace: external_exports.object({
|
|
35332
|
-
old: external_exports.string().min(1),
|
|
35333
|
-
new: external_exports.string()
|
|
35334
|
-
}).optional()
|
|
35335
|
-
});
|
|
35336
|
-
var UpdateMemoryOutputSchema = external_exports.object({
|
|
35337
|
-
memory: external_exports.string().nullable(),
|
|
35338
|
-
// What the memory held before this write — the chat UI's Undo restores it.
|
|
35339
|
-
previousMemory: external_exports.string().nullable()
|
|
35340
|
-
});
|
|
35341
|
-
var toolUpdateMemorySchema = external_exports.object({
|
|
35342
|
-
type: external_exports.literal("tool-update-memory"),
|
|
35343
|
-
toolCallId: external_exports.string().min(1),
|
|
35344
|
-
state: external_exports.literal("input-available"),
|
|
35345
|
-
input: UpdateMemoryInputSchema
|
|
35346
|
-
});
|
|
35347
|
-
var toolUpdateMemoryResultSchema = external_exports.object({
|
|
35348
|
-
type: external_exports.literal("tool-update-memory"),
|
|
35349
|
-
toolCallId: external_exports.string().min(1),
|
|
35350
|
-
state: external_exports.literal("output-available"),
|
|
35351
|
-
input: UpdateMemoryInputSchema,
|
|
35352
|
-
output: UpdateMemoryOutputSchema
|
|
35353
|
-
});
|
|
35354
|
-
|
|
35355
|
-
// ../../packages/sdk/dist/esm/chat-turn/messages.js
|
|
35356
|
-
function createUserMessage(text2) {
|
|
35357
|
-
return {
|
|
35358
|
-
id: globalThis.crypto.randomUUID(),
|
|
35359
|
-
role: "user",
|
|
35360
|
-
parts: [{ type: "text", text: text2 }]
|
|
35361
|
-
};
|
|
35362
|
-
}
|
|
35363
|
-
function toUiMessage(message) {
|
|
35364
|
-
if (message.role !== "user" && message.role !== "assistant" && message.role !== "system") {
|
|
35365
|
-
throw new Error(`Unsupported persisted chat role: ${message.role}`);
|
|
35366
|
-
}
|
|
35367
|
-
if (!Array.isArray(message.parts)) {
|
|
35368
|
-
throw new Error(`Persisted chat message ${message.messageId} has invalid parts.`);
|
|
35369
|
-
}
|
|
35370
|
-
return {
|
|
35371
|
-
id: message.messageId,
|
|
35372
|
-
role: message.role,
|
|
35373
|
-
parts: message.parts
|
|
35374
|
-
};
|
|
35375
|
-
}
|
|
35376
|
-
function getVisibleText(message) {
|
|
35377
|
-
return message.parts.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
35378
|
-
}
|
|
35379
|
-
function getPendingClientAction(message) {
|
|
35380
|
-
for (let index = message.parts.length - 1; index >= 0; index -= 1) {
|
|
35381
|
-
const part = message.parts[index];
|
|
35382
|
-
if (isSelectConnections(part)) {
|
|
35383
|
-
return {
|
|
35384
|
-
kind: "select_connections",
|
|
35385
|
-
message,
|
|
35386
|
-
toolCallId: part.toolCallId,
|
|
35387
|
-
draftId: part.input.draftId,
|
|
35388
|
-
connections: part.input.connections
|
|
35389
|
-
};
|
|
35390
|
-
}
|
|
35391
|
-
if (isPromptEnablePush(part)) {
|
|
35392
|
-
return {
|
|
35393
|
-
kind: "enable_push",
|
|
35394
|
-
message,
|
|
35395
|
-
toolCallId: part.toolCallId,
|
|
35396
|
-
draftId: part.input.draftId
|
|
35397
|
-
};
|
|
35398
|
-
}
|
|
35399
|
-
}
|
|
35400
|
-
return null;
|
|
35401
|
-
}
|
|
35402
|
-
function getPendingActionFromMessages(messages) {
|
|
35403
|
-
const latestMessage = messages.at(-1);
|
|
35404
|
-
if (!latestMessage || latestMessage.role !== "assistant")
|
|
35405
|
-
return null;
|
|
35406
|
-
return getPendingClientAction(toUiMessage(latestMessage));
|
|
35407
|
-
}
|
|
35408
|
-
function getPublishedAutomationId(message) {
|
|
35409
|
-
for (let index = message.parts.length - 1; index >= 0; index -= 1) {
|
|
35410
|
-
const part = message.parts[index];
|
|
35411
|
-
if (isPublishDraftResult(part) && part.output.success) {
|
|
35412
|
-
return part.output.automationId;
|
|
35413
|
-
}
|
|
35414
|
-
}
|
|
35415
|
-
return void 0;
|
|
35416
|
-
}
|
|
35417
|
-
function createEnablePushContinuation(action, output2) {
|
|
35418
|
-
return {
|
|
35419
|
-
id: action.message.id,
|
|
35420
|
-
role: "assistant",
|
|
35421
|
-
parts: [
|
|
35422
|
-
{
|
|
35423
|
-
type: "tool-prompt-enable-push-notifications",
|
|
35424
|
-
toolCallId: action.toolCallId,
|
|
35425
|
-
state: "output-available",
|
|
35426
|
-
output: output2
|
|
35427
|
-
}
|
|
35428
|
-
]
|
|
35429
|
-
};
|
|
35430
|
-
}
|
|
35431
|
-
function createSelectConnectionsContinuation(action, output2) {
|
|
35432
|
-
return {
|
|
35433
|
-
id: action.message.id,
|
|
35434
|
-
role: "assistant",
|
|
35435
|
-
parts: [
|
|
35436
|
-
{
|
|
35437
|
-
type: "tool-select-connections",
|
|
35438
|
-
toolCallId: action.toolCallId,
|
|
35439
|
-
state: "output-available",
|
|
35440
|
-
output: output2
|
|
35441
|
-
}
|
|
35442
|
-
]
|
|
35443
|
-
};
|
|
35444
|
-
}
|
|
35445
|
-
|
|
35446
|
-
// ../../packages/sdk/dist/esm/chat-turn/types.js
|
|
35447
|
-
var ChatTurnInputError = class extends Error {
|
|
35448
|
-
code;
|
|
35449
|
-
constructor(code, message) {
|
|
35450
|
-
super(message);
|
|
35451
|
-
this.name = "ChatTurnInputError";
|
|
35452
|
-
this.code = code;
|
|
35453
|
-
}
|
|
35454
|
-
};
|
|
35455
|
-
|
|
35456
|
-
// ../../packages/sdk/dist/esm/chat-turn/run-conversation-turn.js
|
|
35457
|
-
async function runConversationTurn(options) {
|
|
35458
|
-
const { api, transport, conversationId, signal } = options;
|
|
35459
|
-
const workspaceId = options.workspaceId ?? null;
|
|
35460
|
-
const requestOptions = { signal };
|
|
35461
|
-
const pending = await readPendingAction(options);
|
|
35462
|
-
let nextMessage;
|
|
35463
|
-
if (pending?.kind === "enable_push") {
|
|
35464
|
-
if ("message" in options.input || options.input.selections.length > 0) {
|
|
35465
|
-
throw new ChatTurnInputError("awaiting_push", "The conversation is waiting for the push notification prompt to be answered.");
|
|
35466
|
-
}
|
|
35467
|
-
nextMessage = await answerEnablePush(options, pending);
|
|
35468
|
-
} else if ("message" in options.input) {
|
|
35469
|
-
if (pending?.kind === "select_connections") {
|
|
35470
|
-
throw new ChatTurnInputError("awaiting_selection", "The conversation is waiting for connection selection.");
|
|
35471
|
-
}
|
|
35472
|
-
nextMessage = createUserMessage(options.input.message);
|
|
35473
|
-
} else {
|
|
35474
|
-
const selections = options.input.selections;
|
|
35475
|
-
if (pending?.kind !== "select_connections") {
|
|
35476
|
-
throw new ChatTurnInputError(selections.length > 0 ? "not_awaiting_selection" : "input_required", selections.length > 0 ? "The conversation is not waiting for connection selection." : "A message is required to continue.");
|
|
35477
|
-
}
|
|
35478
|
-
const resolution = await resolveSelectConnections(options, pending, selections);
|
|
35479
|
-
if (resolution.kind === "required") {
|
|
35480
|
-
return actionRequired(conversationId, getVisibleText(pending.message), resolution.pendingAction);
|
|
35481
|
-
}
|
|
35482
|
-
nextMessage = resolution.continuation;
|
|
35483
|
-
}
|
|
35484
|
-
while (true) {
|
|
35485
|
-
const response = await transport.streamTurn({
|
|
35486
|
-
conversationId,
|
|
35487
|
-
workspaceId,
|
|
35488
|
-
message: nextMessage,
|
|
35489
|
-
signal,
|
|
35490
|
-
onText: options.onText,
|
|
35491
|
-
onToolActivity: options.onToolActivity
|
|
35492
|
-
});
|
|
35493
|
-
const assistantText = getVisibleText(response);
|
|
35494
|
-
const automationId = getPublishedAutomationId(response);
|
|
35495
|
-
if (automationId) {
|
|
35496
|
-
options.onPublished?.(automationId);
|
|
35497
|
-
const archive = await archiveConversation(api, conversationId, requestOptions);
|
|
35498
|
-
return {
|
|
35499
|
-
conversationId,
|
|
35500
|
-
outcome: "published",
|
|
35501
|
-
assistantText,
|
|
35502
|
-
automationId,
|
|
35503
|
-
...archive
|
|
35504
|
-
};
|
|
35505
|
-
}
|
|
35506
|
-
const responseAction = getPendingClientAction(response);
|
|
35507
|
-
if (responseAction?.kind === "select_connections") {
|
|
35508
|
-
const resolution = await resolveSelectConnections(options, responseAction, []);
|
|
35509
|
-
if (resolution.kind === "resolved") {
|
|
35510
|
-
nextMessage = resolution.continuation;
|
|
35511
|
-
continue;
|
|
35512
|
-
}
|
|
35513
|
-
return actionRequired(conversationId, assistantText, resolution.pendingAction);
|
|
35514
|
-
}
|
|
35515
|
-
if (responseAction?.kind === "enable_push") {
|
|
35516
|
-
return actionRequired(conversationId, assistantText, {
|
|
35517
|
-
kind: "enable_push",
|
|
35518
|
-
toolCallId: responseAction.toolCallId,
|
|
35519
|
-
draftId: responseAction.draftId
|
|
35520
|
-
});
|
|
35521
|
-
}
|
|
35522
|
-
return { conversationId, outcome: "awaiting_input", assistantText };
|
|
35523
|
-
}
|
|
35524
|
-
}
|
|
35525
|
-
async function answerEnablePush(options, action) {
|
|
35526
|
-
const { subscriptions } = await options.api.notifications.push.list({
|
|
35527
|
-
signal: options.signal
|
|
35528
|
-
});
|
|
35529
|
-
const deviceCount = subscriptions.length;
|
|
35530
|
-
return createEnablePushContinuation(action, {
|
|
35531
|
-
enabled: deviceCount > 0,
|
|
35532
|
-
deviceCount,
|
|
35533
|
-
message: deviceCount > 0 ? `Push notifications are enabled on ${deviceCount} device${deviceCount === 1 ? "" : "s"}.` : "The user has not enabled push notifications."
|
|
35534
|
-
});
|
|
35535
|
-
}
|
|
35536
|
-
async function readPendingAction(options) {
|
|
35537
|
-
if (options.pendingAction !== void 0)
|
|
35538
|
-
return options.pendingAction;
|
|
35539
|
-
const messages = await options.api.chat.getMessages(options.conversationId, {
|
|
35540
|
-
signal: options.signal
|
|
35541
|
-
});
|
|
35542
|
-
return getPendingActionFromMessages(messages);
|
|
35543
|
-
}
|
|
35544
|
-
function actionRequired(conversationId, assistantText, pendingAction) {
|
|
35545
|
-
return { conversationId, outcome: "action_required", assistantText, pendingAction };
|
|
35546
|
-
}
|
|
35547
|
-
async function archiveConversation(api, conversationId, requestOptions) {
|
|
35548
|
-
try {
|
|
35549
|
-
const conversation = await api.chat.updateConversation(conversationId, { isArchived: true }, requestOptions);
|
|
35550
|
-
if (!conversation.isArchived) {
|
|
35551
|
-
throw new Error("The Automations API returned an active conversation.");
|
|
35552
|
-
}
|
|
35553
|
-
return { conversationArchived: true };
|
|
35554
|
-
} catch (error62) {
|
|
35555
|
-
return {
|
|
35556
|
-
conversationArchived: false,
|
|
35557
|
-
conversationArchiveError: error62 instanceof Error ? error62.message : String(error62)
|
|
35558
|
-
};
|
|
35559
|
-
}
|
|
35560
|
-
}
|
|
35561
|
-
async function resolveSelectConnections(options, action, selections) {
|
|
35562
|
-
const { api, signal } = options;
|
|
35563
|
-
const requestOptions = { signal };
|
|
35564
|
-
const requirements = await loadConnectionRequirements(api.connections, action.connections, requestOptions);
|
|
35565
|
-
assertSelectionsUnambiguous(requirements, selections);
|
|
35566
|
-
const resolved = [];
|
|
35567
|
-
for (const requirement of requirements) {
|
|
35568
|
-
const explicit = selections.find((selection) => selection.connectorId === requirement.connectorId && (!selection.connectionType || selection.connectionType === requirement.connectionType));
|
|
35569
|
-
let connectionId = explicit?.connectionId;
|
|
35570
|
-
let setup;
|
|
35571
|
-
if (connectionId) {
|
|
35572
|
-
const exists = requirement.availableConnections.some((connection) => connection.id === connectionId);
|
|
35573
|
-
if (!exists) {
|
|
35574
|
-
throw new ChatTurnInputError("unknown_connection", `Connection ${connectionId} is not an authorized ${requirement.serviceName} connection.`);
|
|
35575
|
-
}
|
|
35576
|
-
} else if (requirement.availableConnections.length === 1) {
|
|
35577
|
-
connectionId = requirement.availableConnections[0]?.id;
|
|
35578
|
-
} else if (requirement.availableConnections.length > 1) {
|
|
35579
|
-
connectionId = await options.chooseConnection?.(requirement);
|
|
35580
|
-
} else if (options.authorizeConnection) {
|
|
35581
|
-
connectionId = await options.authorizeConnection(requirement);
|
|
35582
|
-
} else {
|
|
35583
|
-
setup = await startConnectionSetup(api.connections, { connectorId: requirement.connectorId, capability: requirement.connectionType }, requestOptions);
|
|
35584
|
-
}
|
|
35585
|
-
if (!connectionId) {
|
|
35586
|
-
return {
|
|
35587
|
-
kind: "required",
|
|
35588
|
-
pendingAction: {
|
|
35589
|
-
kind: "select_connections",
|
|
35590
|
-
toolCallId: action.toolCallId,
|
|
35591
|
-
draftId: action.draftId,
|
|
35592
|
-
requirements: requirements.map((item) => item === requirement && setup ? { ...item, setup } : item)
|
|
35593
|
-
}
|
|
35594
|
-
};
|
|
35595
|
-
}
|
|
35596
|
-
resolved.push({ requirement, connectionId });
|
|
35597
|
-
}
|
|
35598
|
-
const output2 = [];
|
|
35599
|
-
for (const item of resolved) {
|
|
35600
|
-
const body = {
|
|
35601
|
-
connectorId: item.requirement.connectorId,
|
|
35602
|
-
connectionType: item.requirement.connectionType,
|
|
35603
|
-
connectionId: item.connectionId
|
|
35604
|
-
};
|
|
35605
|
-
const workspaceId = options.workspaceId ?? null;
|
|
35606
|
-
if (workspaceId === null) {
|
|
35607
|
-
await api.automationDraftConnections.upsert(action.draftId, body, requestOptions);
|
|
35608
|
-
} else {
|
|
35609
|
-
await api.workspaceAutomationDraftConnections.upsert(workspaceId, action.draftId, body, requestOptions);
|
|
35610
|
-
}
|
|
35611
|
-
output2.push({ type: "success", ...body });
|
|
35612
|
-
}
|
|
35613
|
-
return { kind: "resolved", continuation: createSelectConnectionsContinuation(action, output2) };
|
|
35614
|
-
}
|
|
35615
|
-
function assertSelectionsUnambiguous(requirements, selections) {
|
|
35616
|
-
for (const selection of selections) {
|
|
35617
|
-
if (selection.connectionType)
|
|
35618
|
-
continue;
|
|
35619
|
-
const matchingTypes = new Set(requirements.filter((requirement) => requirement.connectorId === selection.connectorId).map((requirement) => requirement.connectionType));
|
|
35620
|
-
if (matchingTypes.size > 1) {
|
|
35621
|
-
throw new ChatTurnInputError("ambiguous_selection", `Connection selection for ${selection.connectorId} is ambiguous. Specify ${selection.connectorId}:mcp or ${selection.connectorId}:trigger.`);
|
|
35622
|
-
}
|
|
35623
|
-
}
|
|
35624
|
-
}
|
|
35625
|
-
|
|
35626
|
-
// ../../packages/sdk/dist/esm/chat-turn/transport.js
|
|
35627
|
-
import { DefaultChatTransport, readUIMessageStream } from "ai";
|
|
35628
|
-
var ChatTurnTransport = class {
|
|
35629
|
-
transport;
|
|
35630
|
-
constructor({ token, baseUrl, headers, fetch: fetch2 }) {
|
|
35631
|
-
const apiRoot = `${baseUrl.replace(/\/+$/, "")}/v1`;
|
|
35632
|
-
this.transport = new DefaultChatTransport({
|
|
35633
|
-
api: `${apiRoot}/chat`,
|
|
35634
|
-
headers: {
|
|
35635
|
-
Authorization: `Bearer ${token}`,
|
|
35636
|
-
...headers
|
|
35637
|
-
},
|
|
35638
|
-
credentials: "include",
|
|
35639
|
-
fetch: fetch2,
|
|
35640
|
-
prepareSendMessagesRequest({ messages, body, api }) {
|
|
35641
|
-
const { workspaceId, ...rest } = body ?? {};
|
|
35642
|
-
return {
|
|
35643
|
-
api: workspaceId ? `${apiRoot}/workspaces/${encodeURIComponent(workspaceId)}/chat` : api,
|
|
35644
|
-
body: {
|
|
35645
|
-
...rest,
|
|
35646
|
-
message: messages.at(-1)
|
|
35647
|
-
}
|
|
35648
|
-
};
|
|
35649
|
-
}
|
|
35650
|
-
});
|
|
35651
|
-
}
|
|
35652
|
-
/** Streams one server turn, reporting incremental text and deduplicated tool state changes. */
|
|
35653
|
-
async streamTurn({ conversationId, workspaceId = null, message, signal, onText, onToolActivity }) {
|
|
35654
|
-
const stream = await this.transport.sendMessages({
|
|
35655
|
-
trigger: "submit-message",
|
|
35656
|
-
chatId: conversationId,
|
|
35657
|
-
messageId: void 0,
|
|
35658
|
-
messages: [message],
|
|
35659
|
-
abortSignal: signal,
|
|
35660
|
-
body: { conversationId, workspaceId }
|
|
35661
|
-
});
|
|
35662
|
-
let finalMessage;
|
|
35663
|
-
let emittedText = "";
|
|
35664
|
-
const emittedToolStates = /* @__PURE__ */ new Set();
|
|
35665
|
-
for await (const currentMessage of readUIMessageStream({
|
|
35666
|
-
stream,
|
|
35667
|
-
terminateOnError: true
|
|
35668
|
-
})) {
|
|
35669
|
-
finalMessage = currentMessage;
|
|
35670
|
-
const visibleText = getVisibleText(currentMessage);
|
|
35671
|
-
if (visibleText.startsWith(emittedText)) {
|
|
35672
|
-
const delta = visibleText.slice(emittedText.length);
|
|
35673
|
-
if (delta)
|
|
35674
|
-
onText?.(delta);
|
|
35675
|
-
emittedText = visibleText;
|
|
35676
|
-
}
|
|
35677
|
-
for (const part of currentMessage.parts) {
|
|
35678
|
-
const activity = toToolActivity(part);
|
|
35679
|
-
if (!activity)
|
|
35680
|
-
continue;
|
|
35681
|
-
const key = `${activity.toolCallId}:${activity.state}`;
|
|
35682
|
-
if (emittedToolStates.has(key))
|
|
35683
|
-
continue;
|
|
35684
|
-
emittedToolStates.add(key);
|
|
35685
|
-
onToolActivity?.(activity);
|
|
35686
|
-
}
|
|
35687
|
-
}
|
|
35688
|
-
if (!finalMessage) {
|
|
35689
|
-
throw new Error("The Automations chat returned an empty response.");
|
|
35690
|
-
}
|
|
35691
|
-
return finalMessage;
|
|
35692
|
-
}
|
|
35693
|
-
};
|
|
35694
|
-
function toToolActivity(part) {
|
|
35695
|
-
if (!part.type.startsWith("tool-") || !("toolCallId" in part) || !("state" in part)) {
|
|
35696
|
-
return null;
|
|
35697
|
-
}
|
|
35698
|
-
return {
|
|
35699
|
-
tool: part.type.slice("tool-".length),
|
|
35700
|
-
toolCallId: String(part.toolCallId),
|
|
35701
|
-
state: String(part.state)
|
|
35702
|
-
};
|
|
35703
|
-
}
|
|
35704
|
-
|
|
35705
35729
|
// src/commands/chat/chat-service.ts
|
|
35706
35730
|
import { createInterface } from "node:readline/promises";
|
|
35707
35731
|
|
|
@@ -38203,6 +38227,9 @@ function registerUpdateCommand(program) {
|
|
|
38203
38227
|
});
|
|
38204
38228
|
}
|
|
38205
38229
|
|
|
38230
|
+
// src/commands/workspace/index.ts
|
|
38231
|
+
import { CliError as CliError9 } from "@doist/cli-core";
|
|
38232
|
+
|
|
38206
38233
|
// src/commands/workspace/format.ts
|
|
38207
38234
|
function formatWorkspaceList(workspaces) {
|
|
38208
38235
|
if (workspaces.length === 0) {
|
|
@@ -38237,7 +38264,25 @@ function registerWorkspaceCommand(program) {
|
|
|
38237
38264
|
workspace.command("list").description("List the workspaces you can use").action(async (_options, command) => {
|
|
38238
38265
|
await runApiCommand(
|
|
38239
38266
|
command,
|
|
38240
|
-
({ api, signal }) =>
|
|
38267
|
+
async ({ api, signal }) => {
|
|
38268
|
+
try {
|
|
38269
|
+
return await api.workspaces.list({ signal });
|
|
38270
|
+
} catch (error62) {
|
|
38271
|
+
if (!(error62 instanceof AutomationsRequestError) || error62.httpStatusCode !== 404) {
|
|
38272
|
+
throw error62;
|
|
38273
|
+
}
|
|
38274
|
+
throw new CliError9(
|
|
38275
|
+
"WORKSPACE_ACCESS_UNAVAILABLE",
|
|
38276
|
+
"Workspace access is not available for this account or environment.",
|
|
38277
|
+
{
|
|
38278
|
+
hints: [
|
|
38279
|
+
"Use your personal space, for example: tda automation list --personal",
|
|
38280
|
+
"Contact support if you expect workspace access."
|
|
38281
|
+
]
|
|
38282
|
+
}
|
|
38283
|
+
);
|
|
38284
|
+
}
|
|
38285
|
+
},
|
|
38241
38286
|
{
|
|
38242
38287
|
human: formatWorkspaceList,
|
|
38243
38288
|
json: summarizeWorkspaceList,
|