@kadoa/mcp 0.5.19 → 0.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -7
- package/dist/index.js +372 -72
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -63,6 +63,7 @@ Point your client to `https://mcp.kadoa.com/mcp` with OAuth authentication.
|
|
|
63
63
|
|------|-------------|
|
|
64
64
|
| `scrape` | Immediately fetch one URL as markdown or raw HTML (shown only for enabled workspaces) |
|
|
65
65
|
| `create_workflow` | Create an agentic navigation workflow from a prompt |
|
|
66
|
+
| `create_realtime_monitor` | Create an asynchronous Julie realtime monitor after persisting notification channels; returns workflow/session/thread/job IDs |
|
|
66
67
|
| `list_workflows` | List all workflows with status |
|
|
67
68
|
| `get_workflow` | Get canonical intent, Assistant/session, template ownership, run health, schedule, location, monitoring, and validation details |
|
|
68
69
|
| `request_workflow_update` | Ask the workflow Assistant to change extraction intent, navigation, sourcing, pagination, or generated behavior without changing the workflow ID |
|
|
@@ -126,9 +127,10 @@ to retrieve the extracted records and display them as a table.
|
|
|
126
127
|
> You: Use my "Product Scraper" template to scrape https://example-shop.com.
|
|
127
128
|
|
|
128
129
|
Claude calls list_templates to find the matching template, then
|
|
129
|
-
create_workflow with `templateId` and `urls` only
|
|
130
|
-
schema
|
|
131
|
-
ID for follow-up with get_workflow
|
|
130
|
+
create_workflow with `templateId` and `urls` only - never copy the prompt,
|
|
131
|
+
entity, or schema into standalone creation. Those values are inherited from
|
|
132
|
+
the template version. Returns the workflow ID for follow-up with get_workflow
|
|
133
|
+
or fetch_data.
|
|
132
134
|
```
|
|
133
135
|
|
|
134
136
|
### Update a workflow and re-run
|
|
@@ -147,8 +149,10 @@ changes, and shows the updated field list.
|
|
|
147
149
|
|
|
148
150
|
> You: Run it again with the new schema.
|
|
149
151
|
|
|
150
|
-
Claude calls run_workflow and
|
|
151
|
-
|
|
152
|
+
Claude calls run_workflow and returns the workflow ID while the run proceeds
|
|
153
|
+
asynchronously. Check back later with get_workflow or fetch_data. If a
|
|
154
|
+
one-time or scheduled workflow fails, call run_workflow again with the same
|
|
155
|
+
workflow ID and configuration - never delete and recreate it just to retry.
|
|
152
156
|
```
|
|
153
157
|
|
|
154
158
|
### Update deterministic workflow settings
|
|
@@ -163,6 +167,20 @@ in `America/New_York`, monitoring fields/conditions, and `limit: null` for all
|
|
|
163
167
|
rows.
|
|
164
168
|
```
|
|
165
169
|
|
|
170
|
+
### Create a Julie realtime monitor
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
> You: Watch https://example-shop.com/products for price changes and alert me by webhook.
|
|
174
|
+
|
|
175
|
+
Claude calls create_realtime_monitor with the URL, schema/change intent, and notification settings. Kadoa persists reusable notification channels first, then Julie asynchronously accepts creation and returns workflow, session, thread, job, and dashboard identifiers.
|
|
176
|
+
|
|
177
|
+
> You: Does Julie need anything from me?
|
|
178
|
+
|
|
179
|
+
Claude uses get_workflow_assistant and the other workflow Assistant tools for follow-up status, questions, interrupts, resumes, or stops. It does not poll or sleep-wait.
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Realtime monitors cannot be converted in place to or from scheduled workflows; create them with `create_realtime_monitor` from the start.
|
|
183
|
+
|
|
166
184
|
### Update an Assistant-built workflow without replacing it
|
|
167
185
|
|
|
168
186
|
```
|
|
@@ -232,14 +250,16 @@ Relevant files in `kadoa-backend`:
|
|
|
232
250
|
|
|
233
251
|
1. Merge PRs to `main` using Conventional Commits (`feat:`, `fix:`, etc.). Release Please opens/maintains a `chore(main): release mcp x.y.z` PR.
|
|
234
252
|
2. Merge the release PR. The [`release-please.yml`](.github/workflows/release-please.yml) workflow tags, drafts a GitHub Release, and publishes to npm (`latest` dist-tag).
|
|
235
|
-
3.
|
|
236
|
-
4. Merge to `main`. CI (`main-build-deploy.yml`) builds and pushes `europe-west3-docker.pkg.dev/oceanic-base-310208/kadoa-artifacts/mcp-server:<IMAGE_TAG>` (tag shown in the build summary).
|
|
253
|
+
3. After npm publication, `release-please.yml` opens or updates a deterministic PR in `kadoa-backend` that bumps `infra/docker/mcp/package.json` and refreshes `bun.lock`. The PR validates a frozen production install and Docker image build, and remains manually mergeable.
|
|
254
|
+
4. Merge the backend PR to `main`. CI (`main-build-deploy.yml`) builds and pushes `europe-west3-docker.pkg.dev/oceanic-base-310208/kadoa-artifacts/mcp-server:<IMAGE_TAG>` (tag shown in the build summary).
|
|
237
255
|
5. Trigger the **Deploy to Production** workflow ([`deploy-prod.yml`](https://github.com/kadoa-org/kadoa-backend/actions/workflows/deploy-prod.yml)) with:
|
|
238
256
|
- **Target cluster:** `gcp`
|
|
239
257
|
- **Deployment scope:** `mcp`
|
|
240
258
|
- **Image tag:** the tag from step 4
|
|
241
259
|
- **Method:** `kubectl`
|
|
242
260
|
|
|
261
|
+
The cross-repository bump requires the `BACKEND_REPO_TOKEN` secret in this repository. The selected authentication approach is a fine-grained PAT scoped only to `kadoa-org/kadoa-backend` with Contents read/write and Pull requests read/write permissions (Metadata read is automatic). If the secret is not provisioned, the release workflow skips the backend bump with a warning rather than failing npm releases; an administrator must provision it before relying on automatic hosted-server updates.
|
|
262
|
+
|
|
243
263
|
### RC / test release
|
|
244
264
|
|
|
245
265
|
Use this when you want to validate a change end-to-end against real clients (Claude Desktop, Cursor, ChatGPT) before promoting to `latest` / prod. The flow mirrors the prod one, but every step targets `rc` channels.
|
package/dist/index.js
CHANGED
|
@@ -45747,6 +45747,25 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
45747
45747
|
constructor(agentApi) {
|
|
45748
45748
|
this.agentApi = agentApi;
|
|
45749
45749
|
}
|
|
45750
|
+
async createRealtimeWorkflow(input) {
|
|
45751
|
+
const response = await this.agentApi.v5AgentPrompt({
|
|
45752
|
+
agentPromptRequest: {
|
|
45753
|
+
prompt: input.instructions,
|
|
45754
|
+
productType: "realtime",
|
|
45755
|
+
notificationChannelIds: input.notificationChannelIds,
|
|
45756
|
+
...input.tags != null && { tags: input.tags },
|
|
45757
|
+
...input.newSessionId != null && { newSessionId: input.newSessionId }
|
|
45758
|
+
}
|
|
45759
|
+
});
|
|
45760
|
+
const data = response.data?.data;
|
|
45761
|
+
if (!data?.workflowId || !data.sessionId || !data.threadId || !Object.keys(data ?? {}).includes("jobId") || data.jobId === undefined) {
|
|
45762
|
+
throw new KadoaSdkException("Realtime Assistant creation response is missing required identifiers", {
|
|
45763
|
+
code: "INTERNAL_ERROR",
|
|
45764
|
+
details: { response: response.data }
|
|
45765
|
+
});
|
|
45766
|
+
}
|
|
45767
|
+
return data;
|
|
45768
|
+
}
|
|
45750
45769
|
async requestWorkflowUpdate(workflowId, input) {
|
|
45751
45770
|
const response = await this.agentApi.v5AgentWorkflowAssistantMessage({
|
|
45752
45771
|
workflowId,
|
|
@@ -45927,6 +45946,28 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
45927
45946
|
options: localVarRequestOptions
|
|
45928
45947
|
};
|
|
45929
45948
|
},
|
|
45949
|
+
v5AgentPrompt: async (agentPromptRequest, options = {}) => {
|
|
45950
|
+
assertParamExists("v5AgentPrompt", "agentPromptRequest", agentPromptRequest);
|
|
45951
|
+
const localVarPath = `/v5/agent`;
|
|
45952
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
45953
|
+
let baseOptions;
|
|
45954
|
+
if (configuration) {
|
|
45955
|
+
baseOptions = configuration.baseOptions;
|
|
45956
|
+
}
|
|
45957
|
+
const localVarRequestOptions = { method: "POST", ...baseOptions, ...options };
|
|
45958
|
+
const localVarHeaderParameter = {};
|
|
45959
|
+
const localVarQueryParameter = {};
|
|
45960
|
+
localVarHeaderParameter["Content-Type"] = "application/json";
|
|
45961
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
45962
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
45963
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
45964
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
45965
|
+
localVarRequestOptions.data = serializeDataIfNeeded(agentPromptRequest, localVarRequestOptions, configuration);
|
|
45966
|
+
return {
|
|
45967
|
+
url: toPathString(localVarUrlObj),
|
|
45968
|
+
options: localVarRequestOptions
|
|
45969
|
+
};
|
|
45970
|
+
},
|
|
45930
45971
|
v5AgentResume: async (sessionId, options = {}) => {
|
|
45931
45972
|
assertParamExists("v5AgentResume", "sessionId", sessionId);
|
|
45932
45973
|
const localVarPath = `/v5/agent/{sessionId}/resume`.replace(`{${"sessionId"}}`, encodeURIComponent(String(sessionId)));
|
|
@@ -46032,6 +46073,12 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
46032
46073
|
const localVarOperationServerBasePath = operationServerMap["AgentApi.v5AgentPauseState"]?.[localVarOperationServerIndex]?.url;
|
|
46033
46074
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
46034
46075
|
},
|
|
46076
|
+
async v5AgentPrompt(agentPromptRequest, options) {
|
|
46077
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v5AgentPrompt(agentPromptRequest, options);
|
|
46078
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
46079
|
+
const localVarOperationServerBasePath = operationServerMap["AgentApi.v5AgentPrompt"]?.[localVarOperationServerIndex]?.url;
|
|
46080
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
46081
|
+
},
|
|
46035
46082
|
async v5AgentResume(sessionId, options) {
|
|
46036
46083
|
const localVarAxiosArgs = await localVarAxiosParamCreator.v5AgentResume(sessionId, options);
|
|
46037
46084
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
@@ -47817,6 +47864,29 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
47817
47864
|
options: localVarRequestOptions
|
|
47818
47865
|
};
|
|
47819
47866
|
},
|
|
47867
|
+
v4TemplatesTemplateIdDuplicatePost: async (templateId, duplicateTemplateBody, options = {}) => {
|
|
47868
|
+
assertParamExists("v4TemplatesTemplateIdDuplicatePost", "templateId", templateId);
|
|
47869
|
+
const localVarPath = `/v4/templates/{templateId}/duplicate`.replace(`{${"templateId"}}`, encodeURIComponent(String(templateId)));
|
|
47870
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
47871
|
+
let baseOptions;
|
|
47872
|
+
if (configuration) {
|
|
47873
|
+
baseOptions = configuration.baseOptions;
|
|
47874
|
+
}
|
|
47875
|
+
const localVarRequestOptions = { method: "POST", ...baseOptions, ...options };
|
|
47876
|
+
const localVarHeaderParameter = {};
|
|
47877
|
+
const localVarQueryParameter = {};
|
|
47878
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
47879
|
+
localVarHeaderParameter["Content-Type"] = "application/json";
|
|
47880
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
47881
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
47882
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
47883
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
47884
|
+
localVarRequestOptions.data = serializeDataIfNeeded(duplicateTemplateBody, localVarRequestOptions, configuration);
|
|
47885
|
+
return {
|
|
47886
|
+
url: toPathString(localVarUrlObj),
|
|
47887
|
+
options: localVarRequestOptions
|
|
47888
|
+
};
|
|
47889
|
+
},
|
|
47820
47890
|
v4TemplatesTemplateIdGet: async (templateId, options = {}) => {
|
|
47821
47891
|
assertParamExists("v4TemplatesTemplateIdGet", "templateId", templateId);
|
|
47822
47892
|
const localVarPath = `/v4/templates/{templateId}`.replace(`{${"templateId"}}`, encodeURIComponent(String(templateId)));
|
|
@@ -48030,6 +48100,12 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48030
48100
|
const localVarOperationServerBasePath = operationServerMap["TemplatesApi.v4TemplatesTemplateIdDelete"]?.[localVarOperationServerIndex]?.url;
|
|
48031
48101
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48032
48102
|
},
|
|
48103
|
+
async v4TemplatesTemplateIdDuplicatePost(templateId, duplicateTemplateBody, options) {
|
|
48104
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4TemplatesTemplateIdDuplicatePost(templateId, duplicateTemplateBody, options);
|
|
48105
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
48106
|
+
const localVarOperationServerBasePath = operationServerMap["TemplatesApi.v4TemplatesTemplateIdDuplicatePost"]?.[localVarOperationServerIndex]?.url;
|
|
48107
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48108
|
+
},
|
|
48033
48109
|
async v4TemplatesTemplateIdGet(templateId, options) {
|
|
48034
48110
|
const localVarAxiosArgs = await localVarAxiosParamCreator.v4TemplatesTemplateIdGet(templateId, options);
|
|
48035
48111
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
@@ -48349,7 +48425,7 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48349
48425
|
options: localVarRequestOptions
|
|
48350
48426
|
};
|
|
48351
48427
|
},
|
|
48352
|
-
v4WorkflowsGet: async (search, skip, limit, state, runState, displayState, inSupport, tags, userId, monitoring, updateInterval, scheduleType, includeDeleted, format, options = {}) => {
|
|
48428
|
+
v4WorkflowsGet: async (search, skip, limit, state, runState, displayState, inSupport, tags, statusFilters, userId, channelId, monitoring, updateInterval, scheduleType, templateId, includeDeleted, format, options = {}) => {
|
|
48353
48429
|
const localVarPath = `/v4/workflows`;
|
|
48354
48430
|
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48355
48431
|
let baseOptions;
|
|
@@ -48384,9 +48460,15 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48384
48460
|
if (tags) {
|
|
48385
48461
|
localVarQueryParameter["tags"] = tags;
|
|
48386
48462
|
}
|
|
48387
|
-
if (
|
|
48463
|
+
if (statusFilters) {
|
|
48464
|
+
localVarQueryParameter["statusFilters"] = statusFilters;
|
|
48465
|
+
}
|
|
48466
|
+
if (userId) {
|
|
48388
48467
|
localVarQueryParameter["userId"] = userId;
|
|
48389
48468
|
}
|
|
48469
|
+
if (channelId) {
|
|
48470
|
+
localVarQueryParameter["channelId"] = channelId;
|
|
48471
|
+
}
|
|
48390
48472
|
if (monitoring !== undefined) {
|
|
48391
48473
|
localVarQueryParameter["monitoring"] = monitoring;
|
|
48392
48474
|
}
|
|
@@ -48396,6 +48478,9 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48396
48478
|
if (scheduleType !== undefined) {
|
|
48397
48479
|
localVarQueryParameter["scheduleType"] = scheduleType;
|
|
48398
48480
|
}
|
|
48481
|
+
if (templateId) {
|
|
48482
|
+
localVarQueryParameter["templateId"] = templateId;
|
|
48483
|
+
}
|
|
48399
48484
|
if (includeDeleted !== undefined) {
|
|
48400
48485
|
localVarQueryParameter["includeDeleted"] = includeDeleted;
|
|
48401
48486
|
}
|
|
@@ -48745,6 +48830,30 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48745
48830
|
options: localVarRequestOptions
|
|
48746
48831
|
};
|
|
48747
48832
|
},
|
|
48833
|
+
v4WorkflowsWorkflowIdHistoryMetricsGet: async (workflowId, days, options = {}) => {
|
|
48834
|
+
assertParamExists("v4WorkflowsWorkflowIdHistoryMetricsGet", "workflowId", workflowId);
|
|
48835
|
+
const localVarPath = `/v4/workflows/{workflowId}/history/metrics`.replace(`{${"workflowId"}}`, encodeURIComponent(String(workflowId)));
|
|
48836
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48837
|
+
let baseOptions;
|
|
48838
|
+
if (configuration) {
|
|
48839
|
+
baseOptions = configuration.baseOptions;
|
|
48840
|
+
}
|
|
48841
|
+
const localVarRequestOptions = { method: "GET", ...baseOptions, ...options };
|
|
48842
|
+
const localVarHeaderParameter = {};
|
|
48843
|
+
const localVarQueryParameter = {};
|
|
48844
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48845
|
+
if (days !== undefined) {
|
|
48846
|
+
localVarQueryParameter["days"] = days;
|
|
48847
|
+
}
|
|
48848
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
48849
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48850
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
48851
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
48852
|
+
return {
|
|
48853
|
+
url: toPathString(localVarUrlObj),
|
|
48854
|
+
options: localVarRequestOptions
|
|
48855
|
+
};
|
|
48856
|
+
},
|
|
48748
48857
|
v4WorkflowsWorkflowIdJobsJobIdGet: async (workflowId, jobId, options = {}) => {
|
|
48749
48858
|
assertParamExists("v4WorkflowsWorkflowIdJobsJobIdGet", "workflowId", workflowId);
|
|
48750
48859
|
assertParamExists("v4WorkflowsWorkflowIdJobsJobIdGet", "jobId", jobId);
|
|
@@ -48812,6 +48921,31 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48812
48921
|
options: localVarRequestOptions
|
|
48813
48922
|
};
|
|
48814
48923
|
},
|
|
48924
|
+
v4WorkflowsWorkflowIdQualityMetricsGet: async (workflowId, jobId, options = {}) => {
|
|
48925
|
+
assertParamExists("v4WorkflowsWorkflowIdQualityMetricsGet", "workflowId", workflowId);
|
|
48926
|
+
const localVarPath = `/v4/workflows/{workflowId}/quality-metrics`.replace(`{${"workflowId"}}`, encodeURIComponent(String(workflowId)));
|
|
48927
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48928
|
+
let baseOptions;
|
|
48929
|
+
if (configuration) {
|
|
48930
|
+
baseOptions = configuration.baseOptions;
|
|
48931
|
+
}
|
|
48932
|
+
const localVarRequestOptions = { method: "GET", ...baseOptions, ...options };
|
|
48933
|
+
const localVarHeaderParameter = {};
|
|
48934
|
+
const localVarQueryParameter = {};
|
|
48935
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48936
|
+
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
|
48937
|
+
if (jobId !== undefined) {
|
|
48938
|
+
localVarQueryParameter["jobId"] = jobId;
|
|
48939
|
+
}
|
|
48940
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
48941
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48942
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
48943
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
48944
|
+
return {
|
|
48945
|
+
url: toPathString(localVarUrlObj),
|
|
48946
|
+
options: localVarRequestOptions
|
|
48947
|
+
};
|
|
48948
|
+
},
|
|
48815
48949
|
v4WorkflowsWorkflowIdResumePut: async (workflowId, options = {}) => {
|
|
48816
48950
|
assertParamExists("v4WorkflowsWorkflowIdResumePut", "workflowId", workflowId);
|
|
48817
48951
|
const localVarPath = `/v4/workflows/{workflowId}/resume`.replace(`{${"workflowId"}}`, encodeURIComponent(String(workflowId)));
|
|
@@ -49033,8 +49167,8 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
49033
49167
|
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsBulkPost"]?.[localVarOperationServerIndex]?.url;
|
|
49034
49168
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
49035
49169
|
},
|
|
49036
|
-
async v4WorkflowsGet(search, skip, limit, state, runState, displayState, inSupport, tags, userId, monitoring, updateInterval, scheduleType, includeDeleted, format, options) {
|
|
49037
|
-
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsGet(search, skip, limit, state, runState, displayState, inSupport, tags, userId, monitoring, updateInterval, scheduleType, includeDeleted, format, options);
|
|
49170
|
+
async v4WorkflowsGet(search, skip, limit, state, runState, displayState, inSupport, tags, statusFilters, userId, channelId, monitoring, updateInterval, scheduleType, templateId, includeDeleted, format, options) {
|
|
49171
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsGet(search, skip, limit, state, runState, displayState, inSupport, tags, statusFilters, userId, channelId, monitoring, updateInterval, scheduleType, templateId, includeDeleted, format, options);
|
|
49038
49172
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
49039
49173
|
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsGet"]?.[localVarOperationServerIndex]?.url;
|
|
49040
49174
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
@@ -49105,6 +49239,12 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
49105
49239
|
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsWorkflowIdHistoryGet"]?.[localVarOperationServerIndex]?.url;
|
|
49106
49240
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
49107
49241
|
},
|
|
49242
|
+
async v4WorkflowsWorkflowIdHistoryMetricsGet(workflowId, days, options) {
|
|
49243
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsWorkflowIdHistoryMetricsGet(workflowId, days, options);
|
|
49244
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
49245
|
+
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsWorkflowIdHistoryMetricsGet"]?.[localVarOperationServerIndex]?.url;
|
|
49246
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
49247
|
+
},
|
|
49108
49248
|
async v4WorkflowsWorkflowIdJobsJobIdGet(workflowId, jobId, options) {
|
|
49109
49249
|
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsWorkflowIdJobsJobIdGet(workflowId, jobId, options);
|
|
49110
49250
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
@@ -49123,6 +49263,12 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
49123
49263
|
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsWorkflowIdPausePut"]?.[localVarOperationServerIndex]?.url;
|
|
49124
49264
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
49125
49265
|
},
|
|
49266
|
+
async v4WorkflowsWorkflowIdQualityMetricsGet(workflowId, jobId, options) {
|
|
49267
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsWorkflowIdQualityMetricsGet(workflowId, jobId, options);
|
|
49268
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
49269
|
+
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsWorkflowIdQualityMetricsGet"]?.[localVarOperationServerIndex]?.url;
|
|
49270
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
49271
|
+
},
|
|
49126
49272
|
async v4WorkflowsWorkflowIdResumePut(workflowId, options) {
|
|
49127
49273
|
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsWorkflowIdResumePut(workflowId, options);
|
|
49128
49274
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
@@ -50276,7 +50422,7 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
50276
50422
|
}));
|
|
50277
50423
|
return channels;
|
|
50278
50424
|
}
|
|
50279
|
-
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.
|
|
50425
|
+
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.38.0", SDK_NAME = "kadoa-node-sdk", SDK_LANGUAGE = "node", debug6, isDrainControlMessage = (message) => message.type === "control.draining", isRealtimeEvent = (message) => message.type !== "heartbeat" && message.type !== "control.draining", _Realtime = class _Realtime2 {
|
|
50280
50426
|
constructor(config2) {
|
|
50281
50427
|
this.drainingSockets = /* @__PURE__ */ new Set;
|
|
50282
50428
|
this.lastHeartbeat = Date.now();
|
|
@@ -51181,7 +51327,17 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
51181
51327
|
return response.data;
|
|
51182
51328
|
}
|
|
51183
51329
|
async list(filters) {
|
|
51184
|
-
|
|
51330
|
+
if (filters == null) {
|
|
51331
|
+
const response2 = await this.workflowsApi.v4WorkflowsGet();
|
|
51332
|
+
return response2.data?.workflows ?? [];
|
|
51333
|
+
}
|
|
51334
|
+
const { templateId, ...rest2 } = filters;
|
|
51335
|
+
const response = await this.workflowsApi.v4WorkflowsGet({
|
|
51336
|
+
...rest2,
|
|
51337
|
+
...templateId != null && {
|
|
51338
|
+
templateId: Array.isArray(templateId) ? templateId : [templateId]
|
|
51339
|
+
}
|
|
51340
|
+
});
|
|
51185
51341
|
return response.data?.workflows ?? [];
|
|
51186
51342
|
}
|
|
51187
51343
|
async getByName(name) {
|
|
@@ -51693,6 +51849,9 @@ var init_dist2 = __esm(() => {
|
|
|
51693
51849
|
v5AgentPauseState(requestParameters, options) {
|
|
51694
51850
|
return AgentApiFp(this.configuration).v5AgentPauseState(requestParameters.sessionId, options).then((request) => request(this.axios, this.basePath));
|
|
51695
51851
|
}
|
|
51852
|
+
v5AgentPrompt(requestParameters, options) {
|
|
51853
|
+
return AgentApiFp(this.configuration).v5AgentPrompt(requestParameters.agentPromptRequest, options).then((request) => request(this.axios, this.basePath));
|
|
51854
|
+
}
|
|
51696
51855
|
v5AgentResume(requestParameters, options) {
|
|
51697
51856
|
return AgentApiFp(this.configuration).v5AgentResume(requestParameters.sessionId, options).then((request) => request(this.axios, this.basePath));
|
|
51698
51857
|
}
|
|
@@ -51907,6 +52066,9 @@ var init_dist2 = __esm(() => {
|
|
|
51907
52066
|
v4TemplatesTemplateIdDelete(requestParameters, options) {
|
|
51908
52067
|
return TemplatesApiFp(this.configuration).v4TemplatesTemplateIdDelete(requestParameters.templateId, options).then((request) => request(this.axios, this.basePath));
|
|
51909
52068
|
}
|
|
52069
|
+
v4TemplatesTemplateIdDuplicatePost(requestParameters, options) {
|
|
52070
|
+
return TemplatesApiFp(this.configuration).v4TemplatesTemplateIdDuplicatePost(requestParameters.templateId, requestParameters.duplicateTemplateBody, options).then((request) => request(this.axios, this.basePath));
|
|
52071
|
+
}
|
|
51910
52072
|
v4TemplatesTemplateIdGet(requestParameters, options) {
|
|
51911
52073
|
return TemplatesApiFp(this.configuration).v4TemplatesTemplateIdGet(requestParameters.templateId, options).then((request) => request(this.axios, this.basePath));
|
|
51912
52074
|
}
|
|
@@ -51963,7 +52125,7 @@ var init_dist2 = __esm(() => {
|
|
|
51963
52125
|
return WorkflowsApiFp(this.configuration).v4WorkflowsBulkPost(requestParameters.v4WorkflowsBulkPostRequest, options).then((request) => request(this.axios, this.basePath));
|
|
51964
52126
|
}
|
|
51965
52127
|
v4WorkflowsGet(requestParameters = {}, options) {
|
|
51966
|
-
return WorkflowsApiFp(this.configuration).v4WorkflowsGet(requestParameters.search, requestParameters.skip, requestParameters.limit, requestParameters.state, requestParameters.runState, requestParameters.displayState, requestParameters.inSupport, requestParameters.tags, requestParameters.userId, requestParameters.monitoring, requestParameters.updateInterval, requestParameters.scheduleType, requestParameters.includeDeleted, requestParameters.format, options).then((request) => request(this.axios, this.basePath));
|
|
52128
|
+
return WorkflowsApiFp(this.configuration).v4WorkflowsGet(requestParameters.search, requestParameters.skip, requestParameters.limit, requestParameters.state, requestParameters.runState, requestParameters.displayState, requestParameters.inSupport, requestParameters.tags, requestParameters.statusFilters, requestParameters.userId, requestParameters.channelId, requestParameters.monitoring, requestParameters.updateInterval, requestParameters.scheduleType, requestParameters.templateId, requestParameters.includeDeleted, requestParameters.format, options).then((request) => request(this.axios, this.basePath));
|
|
51967
52129
|
}
|
|
51968
52130
|
v4WorkflowsPost(requestParameters = {}, options) {
|
|
51969
52131
|
return WorkflowsApiFp(this.configuration).v4WorkflowsPost(requestParameters.publicWorkflowCreateRequest, options).then((request) => request(this.axios, this.basePath));
|
|
@@ -51998,6 +52160,9 @@ var init_dist2 = __esm(() => {
|
|
|
51998
52160
|
v4WorkflowsWorkflowIdHistoryGet(requestParameters, options) {
|
|
51999
52161
|
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdHistoryGet(requestParameters.workflowId, requestParameters.page, requestParameters.limit, requestParameters.status, options).then((request) => request(this.axios, this.basePath));
|
|
52000
52162
|
}
|
|
52163
|
+
v4WorkflowsWorkflowIdHistoryMetricsGet(requestParameters, options) {
|
|
52164
|
+
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdHistoryMetricsGet(requestParameters.workflowId, requestParameters.days, options).then((request) => request(this.axios, this.basePath));
|
|
52165
|
+
}
|
|
52001
52166
|
v4WorkflowsWorkflowIdJobsJobIdGet(requestParameters, options) {
|
|
52002
52167
|
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdJobsJobIdGet(requestParameters.workflowId, requestParameters.jobId, options).then((request) => request(this.axios, this.basePath));
|
|
52003
52168
|
}
|
|
@@ -52007,6 +52172,9 @@ var init_dist2 = __esm(() => {
|
|
|
52007
52172
|
v4WorkflowsWorkflowIdPausePut(requestParameters, options) {
|
|
52008
52173
|
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdPausePut(requestParameters.workflowId, options).then((request) => request(this.axios, this.basePath));
|
|
52009
52174
|
}
|
|
52175
|
+
v4WorkflowsWorkflowIdQualityMetricsGet(requestParameters, options) {
|
|
52176
|
+
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdQualityMetricsGet(requestParameters.workflowId, requestParameters.jobId, options).then((request) => request(this.axios, this.basePath));
|
|
52177
|
+
}
|
|
52010
52178
|
v4WorkflowsWorkflowIdResumePut(requestParameters, options) {
|
|
52011
52179
|
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdResumePut(requestParameters.workflowId, options).then((request) => request(this.axios, this.basePath));
|
|
52012
52180
|
}
|
|
@@ -52531,7 +52699,7 @@ function extractApiMessage(responseBody) {
|
|
|
52531
52699
|
if (body.validationErrors && typeof body.validationErrors === "object" && body.validationErrors !== null) {
|
|
52532
52700
|
const details = Object.entries(body.validationErrors).map(([field, err]) => `${field}: "${err}"`).join(", ");
|
|
52533
52701
|
if (details) {
|
|
52534
|
-
msg = msg ? `${msg}
|
|
52702
|
+
msg = msg ? `${msg} - Details: ${details}` : `Validation failed - Details: ${details}`;
|
|
52535
52703
|
}
|
|
52536
52704
|
}
|
|
52537
52705
|
if (!msg && Array.isArray(body.issues)) {
|
|
@@ -52541,7 +52709,7 @@ function extractApiMessage(responseBody) {
|
|
|
52541
52709
|
return path ? `${path}: "${message}"` : `"${message}"`;
|
|
52542
52710
|
}).join(", ");
|
|
52543
52711
|
if (details)
|
|
52544
|
-
msg = `Validation failed
|
|
52712
|
+
msg = `Validation failed - Details: ${details}`;
|
|
52545
52713
|
}
|
|
52546
52714
|
return msg;
|
|
52547
52715
|
}
|
|
@@ -52727,14 +52895,14 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52727
52895
|
});
|
|
52728
52896
|
}));
|
|
52729
52897
|
const urlInputShape = {
|
|
52730
|
-
url: exports_external.string().optional().describe("Single URL
|
|
52898
|
+
url: exports_external.string().optional().describe("Single URL - prefer using 'urls' instead. If both are provided, 'urls' takes precedence."),
|
|
52731
52899
|
urls: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string()).min(1)).optional().describe("Starting URLs for the workflow (array of strings). Also accepts a single URL string.")
|
|
52732
52900
|
};
|
|
52733
52901
|
const extractionInputShape = {
|
|
52734
52902
|
prompt: exports_external.string().optional().describe('Natural language description of what to extract (e.g., "Extract product prices and names"). Required unless templateId is provided.'),
|
|
52735
52903
|
name: exports_external.string().optional().describe("Optional name for the workflow"),
|
|
52736
52904
|
entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
|
|
52737
|
-
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("Extraction schema fields. If omitted, the AI agent auto-detects the schema. When you do supply fields, mark the one that identifies a record with isKey
|
|
52905
|
+
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("Extraction schema fields. If omitted, the AI agent auto-detects the schema. When you do supply fields, mark the one that identifies a record with isKey - change detection needs it.")
|
|
52738
52906
|
};
|
|
52739
52907
|
const webhookAuthShape = exports_external.object({
|
|
52740
52908
|
type: exports_external.enum(["bearer", "basic", "header"]).describe("Authentication type"),
|
|
@@ -52765,6 +52933,33 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52765
52933
|
const urls = args.urls ?? (args.url ? [args.url] : []);
|
|
52766
52934
|
return urls.length > 0 ? urls : null;
|
|
52767
52935
|
}
|
|
52936
|
+
function buildRealtimeAssistantInstructions(args, urls) {
|
|
52937
|
+
const lines = ["Create a realtime monitoring workflow with Julie.", "", "Source URLs:"];
|
|
52938
|
+
for (const url3 of urls)
|
|
52939
|
+
lines.push(`- ${url3}`);
|
|
52940
|
+
if (args.prompt)
|
|
52941
|
+
lines.push("", "User prompt:", args.prompt);
|
|
52942
|
+
if (args.name)
|
|
52943
|
+
lines.push("", `Requested workflow name: ${args.name}`);
|
|
52944
|
+
if (args.description)
|
|
52945
|
+
lines.push(`Requested workflow description: ${args.description}`);
|
|
52946
|
+
if (args.entity)
|
|
52947
|
+
lines.push("", `Entity to monitor: ${args.entity}`);
|
|
52948
|
+
if (args.schema?.length) {
|
|
52949
|
+
lines.push("", "Schema fields to preserve:");
|
|
52950
|
+
for (const field of args.schema) {
|
|
52951
|
+
lines.push(`- ${field.name}`);
|
|
52952
|
+
lines.push(` Data type: ${field.dataType || "STRING"}`);
|
|
52953
|
+
lines.push(` Key field: ${field.isKey ? "yes" : "no"}`);
|
|
52954
|
+
if (field.description)
|
|
52955
|
+
lines.push(` Description: ${field.description}`);
|
|
52956
|
+
lines.push(` Example: ${field.example}`);
|
|
52957
|
+
}
|
|
52958
|
+
}
|
|
52959
|
+
lines.push("", "Monitor continuously for data changes and preserve these requirements while building the workflow.");
|
|
52960
|
+
return lines.join(`
|
|
52961
|
+
`);
|
|
52962
|
+
}
|
|
52768
52963
|
function buildExtraction(args) {
|
|
52769
52964
|
if (!args.schema)
|
|
52770
52965
|
return;
|
|
@@ -52835,15 +53030,15 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52835
53030
|
return channels;
|
|
52836
53031
|
}
|
|
52837
53032
|
server.registerTool("create_workflow", {
|
|
52838
|
-
description: "IMPORTANT: One workflow = one source. A single workflow can extract many different fields, tables, and sections from the same URL(s) using a rich schema. " + `Do NOT create separate workflows for different data points on the same page
|
|
53033
|
+
description: "IMPORTANT: One workflow = one source. A single workflow can extract many different fields, tables, and sections from the same URL(s) using a rich schema. " + `Do NOT create separate workflows for different data points on the same page - instead, define one workflow with a multi-field schema covering everything needed.
|
|
52839
53034
|
|
|
52840
53035
|
` + "Create a data extraction workflow using agentic navigation. Supports one-time or scheduled runs. " + "If entity and schema are provided, they guide the extraction; otherwise the AI agent auto-detects the schema from the page. " + "The workflow runs asynchronously and may take several minutes. Do NOT poll or sleep-wait for completion. " + `Return the workflow ID to the user and let them check back later with get_workflow or fetch_data.
|
|
52841
53036
|
|
|
52842
|
-
` + "PREFER TEMPLATES: If the user's request matches an existing template, instantiate it via `templateId` instead of writing a fresh prompt/schema. " + "Use `list_templates` to discover available templates and `get_template` to inspect schemas before deciding. " + "When
|
|
53037
|
+
` + "PREFER TEMPLATES: If the user's request matches an existing template, instantiate it via `templateId` instead of writing a fresh prompt/schema. " + "Use `list_templates` to discover available templates and `get_template` to inspect schemas before deciding. " + "When creating from a template, call this tool with the template's `templateId`, the source `urls`, and optional `templateVersion` only. Never copy the template prompt, entity, or schema into standalone creation, and never silently match or rewrite inline configuration.\n\n" + "NOTE: This tool is for one-time or scheduled extraction ONLY. " + "For continuous Julie realtime monitoring (watching a page for data changes and alerting), use the create_realtime_monitor tool instead.",
|
|
52843
53038
|
inputSchema: strictSchema({
|
|
52844
53039
|
...extractionInputShape,
|
|
52845
53040
|
...urlInputShape,
|
|
52846
|
-
templateId: exports_external.string().optional().describe("Instantiate this workflow from a published template.
|
|
53041
|
+
templateId: exports_external.string().optional().describe("Instantiate this workflow from a published template. Pass the templateId, source urls, and optional templateVersion. Do not copy prompt/entity/schema from the template into this call - they are inherited from the published template version, and the workflow's output conforms to its declared schema. Discover templates via list_templates and get_template."),
|
|
52847
53042
|
templateVersion: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Specific published template version (integer) to instantiate. Defaults to the latest published version when templateId is set."),
|
|
52848
53043
|
description: exports_external.string().max(500).optional().describe("Description of what this workflow does (max 500 characters)"),
|
|
52849
53044
|
tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing workflows"),
|
|
@@ -52884,7 +53079,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52884
53079
|
let workflowId;
|
|
52885
53080
|
if (args.templateId) {
|
|
52886
53081
|
if (args.prompt || args.entity || args.schema) {
|
|
52887
|
-
return errorResult("When 'templateId' is set, 'prompt', 'entity', and 'schema' must NOT be supplied
|
|
53082
|
+
return errorResult("When 'templateId' is set, 'prompt', 'entity', and 'schema' must NOT be supplied - they are inherited from the template version.");
|
|
52888
53083
|
}
|
|
52889
53084
|
const { id } = await ctx.client.workflow.create({
|
|
52890
53085
|
urls,
|
|
@@ -52950,9 +53145,9 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52950
53145
|
});
|
|
52951
53146
|
}));
|
|
52952
53147
|
server.registerTool("create_realtime_monitor", {
|
|
52953
|
-
description: "Create a
|
|
53148
|
+
description: "Create a Julie realtime monitoring workflow that continuously watches a page for data changes and sends alerts. " + "Use this when the user wants to monitor, track, or watch a page in realtime. " + "At least one notification channel (email, webhook, slack, or websocket) is required; notification settings are persisted before Julie is dispatched. " + `Realtime monitors CANNOT be converted to/from regular extraction workflows after creation.
|
|
52954
53149
|
|
|
52955
|
-
` + "If entity and schema are provided, they guide what
|
|
53150
|
+
` + "If entity and schema are provided, they guide what Julie should monitor; otherwise Julie auto-detects what to watch. " + "Creation is asynchronous and the response includes workflow, session, thread, and job IDs plus a dashboard URL. " + "Use generic workflow Assistant tools (get_workflow_assistant, answer_workflow_assistant_question, interrupt_workflow_assistant, resume_workflow_assistant, stop_workflow_assistant) for follow-up status, questions, and controls. " + "Do NOT poll or sleep-wait for completion.",
|
|
52956
53151
|
inputSchema: strictSchema({
|
|
52957
53152
|
...extractionInputShape,
|
|
52958
53153
|
...urlInputShape,
|
|
@@ -52971,33 +53166,33 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52971
53166
|
if (!hasNotifications) {
|
|
52972
53167
|
return errorResult("Real-time monitors require at least one notification channel so you get alerted when data changes. " + "Add a notifications object with one or more channels: email, webhook, slack, or websocket.");
|
|
52973
53168
|
}
|
|
52974
|
-
|
|
52975
|
-
urls,
|
|
52976
|
-
name: args.name || "Untitled Monitor",
|
|
52977
|
-
userPrompt: args.prompt,
|
|
52978
|
-
extraction: buildExtraction(args),
|
|
52979
|
-
interval: "REAL_TIME",
|
|
52980
|
-
description: args.description
|
|
52981
|
-
});
|
|
52982
|
-
builder = builder.withNotifications({
|
|
52983
|
-
events: ["workflow_data_change"],
|
|
53169
|
+
const channels = await ctx.client.notification.setup.setupChannels({
|
|
52984
53170
|
channels: buildNotificationChannels(n)
|
|
52985
53171
|
});
|
|
52986
|
-
const
|
|
52987
|
-
if (
|
|
52988
|
-
|
|
53172
|
+
const notificationChannelIds = channels.map((channel) => channel.id).filter((id) => typeof id === "string" && id.length > 0);
|
|
53173
|
+
if (notificationChannelIds.length === 0) {
|
|
53174
|
+
return errorResult("No usable notification channels were configured for the realtime monitor.");
|
|
52989
53175
|
}
|
|
52990
|
-
const
|
|
52991
|
-
|
|
52992
|
-
|
|
52993
|
-
|
|
53176
|
+
const result = await ctx.client.assistant.createRealtimeWorkflow({
|
|
53177
|
+
instructions: buildRealtimeAssistantInstructions(args, urls),
|
|
53178
|
+
notificationChannelIds,
|
|
53179
|
+
...args.tags?.length ? { tags: args.tags } : {}
|
|
53180
|
+
});
|
|
53181
|
+
if (!result || typeof result.workflowId !== "string" || result.workflowId.length === 0 || typeof result.sessionId !== "string" || result.sessionId.length === 0 || typeof result.threadId !== "string" || result.threadId.length === 0 || typeof result.jobId !== "string" || result.jobId.length === 0) {
|
|
53182
|
+
throw new KadoaSdkException("Realtime Assistant creation response is missing required identifiers", {
|
|
53183
|
+
code: "INTERNAL_ERROR",
|
|
53184
|
+
details: { response: result }
|
|
53185
|
+
});
|
|
52994
53186
|
}
|
|
52995
|
-
message += " Use fetch_data to retrieve the latest data.";
|
|
52996
53187
|
return jsonResult({
|
|
52997
53188
|
success: true,
|
|
52998
|
-
|
|
52999
|
-
|
|
53000
|
-
|
|
53189
|
+
status: "accepted",
|
|
53190
|
+
workflowId: result.workflowId,
|
|
53191
|
+
sessionId: result.sessionId,
|
|
53192
|
+
threadId: result.threadId,
|
|
53193
|
+
jobId: result.jobId,
|
|
53194
|
+
dashboardUrl: workflowDashboardUrl(result.workflowId),
|
|
53195
|
+
message: "Julie realtime workflow creation accepted. Notification settings were persisted before Julie dispatch. Creation is asynchronous; use get_workflow_assistant for status, questions, or controls, and do not poll or sleep-wait."
|
|
53001
53196
|
});
|
|
53002
53197
|
}));
|
|
53003
53198
|
server.registerTool("list_workflows", {
|
|
@@ -53040,7 +53235,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53040
53235
|
});
|
|
53041
53236
|
}));
|
|
53042
53237
|
server.registerTool("get_workflow", {
|
|
53043
|
-
description: "Get canonical workflow details, including Assistant/session linkage, extraction intent, template-controlled parts, stale-data state, job/run state, schedule timezone, location, monitoring, validation, and realtime health. For Assistant-built workflows, extractionSpec
|
|
53238
|
+
description: "Get canonical workflow details, including Assistant/session linkage, extraction intent, template-controlled parts, stale-data state, job/run state, schedule timezone, location, monitoring, validation, and realtime health. For Assistant-built workflows, extractionSpec - not the legacy prompt - is authoritative.",
|
|
53044
53239
|
inputSchema: {
|
|
53045
53240
|
workflowId: exports_external.string().describe("The workflow ID")
|
|
53046
53241
|
},
|
|
@@ -53404,7 +53599,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53404
53599
|
});
|
|
53405
53600
|
}));
|
|
53406
53601
|
server.registerTool("list_workflow_runs", {
|
|
53407
|
-
description: "List a workflow's execution run history
|
|
53602
|
+
description: "List a workflow's execution run history - each run's status, start/finish time, " + "record count, and errors. Use to answer 'when did this last succeed?' " + "(status='success', limit=1) or 'recent success/failure pattern?'. Distinct from " + "get_workflow_history, which is the config audit log. `status` is normally " + "success | failed | in_progress; a run whose backend state this server does not " + "recognize reports that raw state verbatim, so treat any other value as unknown " + "rather than as a failure.",
|
|
53408
53603
|
inputSchema: {
|
|
53409
53604
|
workflowId: exports_external.string().describe("The workflow ID"),
|
|
53410
53605
|
status: exports_external.enum(["success", "failed", "in_progress"]).optional().describe("Filter runs by outcome"),
|
|
@@ -53433,7 +53628,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53433
53628
|
});
|
|
53434
53629
|
}));
|
|
53435
53630
|
server.registerTool("run_workflow", {
|
|
53436
|
-
description: "Run a workflow to extract fresh data. The run is asynchronous and may take several minutes. Do NOT poll or sleep-wait for completion. Return the workflow ID to the user and let them check status with get_workflow or fetch results later with fetch_data.",
|
|
53631
|
+
description: "Run a workflow to extract fresh data, including retrying a failed one-time or scheduled workflow. Preserve the existing workflow ID and configuration - do not delete and recreate the workflow solely to retry it. The run is asynchronous and may take several minutes. Do NOT poll or sleep-wait for completion. Return the workflow ID to the user and let them check status with get_workflow or fetch results later with fetch_data. Realtime workflows cannot be manually run.",
|
|
53437
53632
|
inputSchema: {
|
|
53438
53633
|
workflowId: exports_external.string().describe("The workflow ID to run"),
|
|
53439
53634
|
limit: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Maximum number of records to extract (default: 1000)")
|
|
@@ -53456,7 +53651,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53456
53651
|
const FETCH_DATA_DEFAULT_LIMIT = 50;
|
|
53457
53652
|
const FETCH_DATA_MAX_LIMIT = 500;
|
|
53458
53653
|
server.registerTool("fetch_data", {
|
|
53459
|
-
description: "Get a PAGE of extracted data from a workflow. Use ONLY for previews, sorted/filtered slices, or explicit 'first N rows' / 'top N' queries (capped at 500 rows per call). Do NOT use this to retrieve a full dataset, 'all rows', or anything the user wants to analyze in Excel / pandas / duckdb
|
|
53654
|
+
description: "Get a PAGE of extracted data from a workflow. Use ONLY for previews, sorted/filtered slices, or explicit 'first N rows' / 'top N' queries (capped at 500 rows per call). Do NOT use this to retrieve a full dataset, 'all rows', or anything the user wants to analyze in Excel / pandas / duckdb - use export_data for those. Data is only available after the workflow run has completed (status is no longer 'Running' or 'Validating'). Do NOT poll or sleep-wait for completion.",
|
|
53460
53655
|
inputSchema: {
|
|
53461
53656
|
workflowId: exports_external.string().describe("The workflow ID"),
|
|
53462
53657
|
limit: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe(`Maximum number of records to return. Default ${FETCH_DATA_DEFAULT_LIMIT}, max ${FETCH_DATA_MAX_LIMIT}.`),
|
|
@@ -53491,7 +53686,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53491
53686
|
return jsonResult(result);
|
|
53492
53687
|
}));
|
|
53493
53688
|
server.registerTool("export_data", {
|
|
53494
|
-
description: "PREFERRED tool for retrieving a workflow's FULL dataset. Materializes the data to object storage and returns a signed download URL. Use this whenever the user wants 'all rows', 'the full dataset', 'everything', an export, or anything destined for Excel / pandas / duckdb / a CSV file
|
|
53689
|
+
description: "PREFERRED tool for retrieving a workflow's FULL dataset. Materializes the data to object storage and returns a signed download URL. Use this whenever the user wants 'all rows', 'the full dataset', 'everything', an export, or anything destined for Excel / pandas / duckdb / a CSV file - even for small workflows. The URL is self-authenticating (open with `fetch(url)`, no Authorization header). Use fetch_data ONLY when the user explicitly asks for a small preview slice (e.g., 'first 10', 'top N sorted by X').",
|
|
53495
53690
|
inputSchema: {
|
|
53496
53691
|
workflowId: exports_external.string().describe("The workflow ID"),
|
|
53497
53692
|
format: exports_external.enum(["csv", "json"]).optional().describe("Export format. Default 'csv'."),
|
|
@@ -53523,7 +53718,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53523
53718
|
});
|
|
53524
53719
|
}));
|
|
53525
53720
|
server.registerTool("list_changes", {
|
|
53526
|
-
description: "List detected data changes across one or more
|
|
53721
|
+
description: "List detected data changes across one or more Julie realtime monitoring workflows. " + "Returns structured diffs showing added, removed, and changed records. " + "Only works for workflows with realtime monitoring enabled.",
|
|
53527
53722
|
inputSchema: {
|
|
53528
53723
|
workflowIds: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Workflow IDs to filter by. If omitted, returns changes for all ACTIVE monitoring workflows."),
|
|
53529
53724
|
startDate: exports_external.string().optional().describe("Start date filter (ISO format, e.g. 2025-01-01)"),
|
|
@@ -53617,7 +53812,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53617
53812
|
});
|
|
53618
53813
|
}));
|
|
53619
53814
|
server.registerTool("pause_workflow", {
|
|
53620
|
-
description: "Pause an ACTIVE workflow so it stops running on its schedule. Requires the workflow to be in ACTIVE state
|
|
53815
|
+
description: "Pause an ACTIVE workflow so it stops running on its schedule. Requires the workflow to be in ACTIVE state - pausing a workflow that is currently running, already paused, or in PREVIEW will return an error. Use approve_workflow to resume a paused workflow.",
|
|
53621
53816
|
inputSchema: {
|
|
53622
53817
|
workflowId: exports_external.string().min(1).describe("The workflow ID to pause")
|
|
53623
53818
|
},
|
|
@@ -53631,17 +53826,17 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53631
53826
|
});
|
|
53632
53827
|
}));
|
|
53633
53828
|
server.registerTool("update_workflow", {
|
|
53634
|
-
description: `Update a workflow's configuration. All fields are optional
|
|
53829
|
+
description: `Update a workflow's configuration. All fields are optional - only provided fields will be updated. Use this to change the name, URLs, extraction schema, entity, prompt, schedule, or other metadata.
|
|
53635
53830
|
|
|
53636
|
-
` + `IMPORTANT: You cannot change a workflow's interval to or from REAL_TIME.
|
|
53831
|
+
` + `IMPORTANT: You cannot change a workflow's interval to or from REAL_TIME. Julie realtime workflows are architecturally different from scheduled workflows and must be created with create_realtime_monitor from the start. Existing workflows cannot be converted between these modes in place; do not delete and recreate a workflow as an update workaround.
|
|
53637
53832
|
|
|
53638
|
-
` + "ASSISTANT-OWNED INTENT: Use request_workflow_update
|
|
53833
|
+
` + "ASSISTANT-OWNED INTENT: Use request_workflow_update - not `userPrompt` - for agent-built workflow changes to extraction intent, navigation, pagination, data sourcing, repair, or generated scripts. `userPrompt` may be rejected with `SHELLY_INTENT_REQUIRES_EXTRACTION_SPEC` because those workflows' canonical intent is owned by the Assistant. " + "Call get_workflow first. If its template.controlledParts contains the setting, create and apply a template version instead of overriding the workflow directly. NEVER delete and recreate a workflow to work around an update limitation - that changes workflowId, breaks downstream tables/connectors, and discards history.",
|
|
53639
53834
|
inputSchema: strictSchema({
|
|
53640
53835
|
workflowId: exports_external.string().describe("The workflow ID to update"),
|
|
53641
53836
|
name: exports_external.string().optional().describe("New name for the workflow"),
|
|
53642
53837
|
urls: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string()).min(1)).optional().describe("New target URLs for the workflow (array of strings). Also accepts a single URL string."),
|
|
53643
53838
|
entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
|
|
53644
|
-
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("New extraction schema fields. This REPLACES the whole schema
|
|
53839
|
+
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("New extraction schema fields. This REPLACES the whole schema - list every field you want to keep, each with its isKey flag, or the omitted ones and their flags are lost. Call get_workflow first and edit the schema it returns."),
|
|
53645
53840
|
description: exports_external.string().max(500).optional().describe("Workflow description (max 500 characters)"),
|
|
53646
53841
|
tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing workflows"),
|
|
53647
53842
|
userPrompt: exports_external.string().optional().describe("Navigation prompt for agentic-navigation mode (10-5000 characters)"),
|
|
@@ -53663,7 +53858,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53663
53858
|
"FOUR_WEEKS",
|
|
53664
53859
|
"MONTHLY",
|
|
53665
53860
|
"CUSTOM"
|
|
53666
|
-
]).optional().describe("How often the workflow should run. CUSTOM requires schedules. Note: REAL_TIME is NOT allowed here
|
|
53861
|
+
]).optional().describe("How often the workflow should run. CUSTOM requires schedules. Note: REAL_TIME is NOT allowed here - realtime workflows must be created via create_realtime_monitor."),
|
|
53667
53862
|
schedules: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Cron expressions for CUSTOM update interval"),
|
|
53668
53863
|
timezone: exports_external.string().min(1).optional().describe("IANA timezone for cron schedules, for example America/New_York. A timezone-only update preserves existing cron expressions."),
|
|
53669
53864
|
location: exports_external.preprocess(coerceJson(), LocationSchema).optional().describe("Scraping location: {type:'auto'} or {type:'manual', isoCode:'US'}"),
|
|
@@ -53678,10 +53873,10 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53678
53873
|
const isCurrentlyRealTime = isRealTimeInterval(workflow.updateInterval);
|
|
53679
53874
|
const isRequestingRealTime = isRealTimeInterval(updates.updateInterval);
|
|
53680
53875
|
if (isRequestingRealTime && !isCurrentlyRealTime) {
|
|
53681
|
-
return errorResult("Cannot change a regular workflow's interval to REAL_TIME. " + "
|
|
53876
|
+
return errorResult("Cannot change a regular workflow's interval to REAL_TIME. " + "Julie realtime workflows cannot replace this workflow in place. " + "The existing workflow was left unchanged.");
|
|
53682
53877
|
}
|
|
53683
53878
|
if (!isRequestingRealTime && isCurrentlyRealTime) {
|
|
53684
|
-
return errorResult("Cannot change a
|
|
53879
|
+
return errorResult("Cannot change a Julie realtime workflow's interval to a scheduled interval. " + "Julie realtime workflows are architecturally different and cannot be converted in place. " + "The existing workflow was left unchanged.");
|
|
53685
53880
|
}
|
|
53686
53881
|
}
|
|
53687
53882
|
if (updates.updateInterval === "CUSTOM" && (!updates.schedules || updates.schedules.length === 0)) {
|
|
@@ -54082,22 +54277,29 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54082
54277
|
});
|
|
54083
54278
|
}));
|
|
54084
54279
|
server.registerTool("list_templates", {
|
|
54085
|
-
description: "List all templates in the current team. Templates define reusable configurations (prompt, schema, notifications).",
|
|
54280
|
+
description: "List all templates in the current team. Templates define reusable configurations (prompt, schema, validation rules, notifications, and frequency). Use this to find a matching template before creating a workflow. To instantiate a template, call create_workflow with its templateId, source URLs, and optional templateVersion - never copy the template prompt, entity, or schema into standalone creation.",
|
|
54086
54281
|
inputSchema: strictSchema({}),
|
|
54087
54282
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
|
|
54088
54283
|
}, withErrorHandling("list_templates", async () => {
|
|
54089
54284
|
const templates = await ctx.client.template.list();
|
|
54090
|
-
return jsonResult({
|
|
54285
|
+
return jsonResult({
|
|
54286
|
+
templates,
|
|
54287
|
+
count: templates.length,
|
|
54288
|
+
instructions: "To instantiate a listed template, call create_workflow with the matching templateId, source URLs, and optional templateVersion. Do not copy the template prompt, entity, or schema into standalone creation."
|
|
54289
|
+
});
|
|
54091
54290
|
}));
|
|
54092
54291
|
server.registerTool("get_template", {
|
|
54093
|
-
description: "Get a template by ID, including all published versions.",
|
|
54292
|
+
description: "Get a template by ID, including all published versions and their schemas. After inspecting it, instantiate the template with create_workflow using templateId, source URLs, and optional templateVersion. Never copy the returned prompt, entity, or schema into standalone creation - those values are inherited when templateId is passed.",
|
|
54094
54293
|
inputSchema: strictSchema({
|
|
54095
54294
|
templateId: exports_external.string().describe("The template ID")
|
|
54096
54295
|
}),
|
|
54097
54296
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
|
|
54098
54297
|
}, withErrorHandling("get_template", async (args) => {
|
|
54099
54298
|
const template = await ctx.client.template.get(args.templateId);
|
|
54100
|
-
return jsonResult({
|
|
54299
|
+
return jsonResult({
|
|
54300
|
+
template,
|
|
54301
|
+
instructions: `To instantiate this template, call create_workflow with templateId "${args.templateId}", source URLs, and optional templateVersion. Do not copy this template's prompt, entity, or schema into standalone creation.`
|
|
54302
|
+
});
|
|
54101
54303
|
}));
|
|
54102
54304
|
server.registerTool("create_template", {
|
|
54103
54305
|
description: "Create a new template. After creation, use create_template_version to publish a version with prompt, schema, and notifications.",
|
|
@@ -54120,7 +54322,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54120
54322
|
server.registerTool("update_template", {
|
|
54121
54323
|
description: `Update a template's name or description ONLY. At least one of the two must be provided.
|
|
54122
54324
|
|
|
54123
|
-
` + "This tool CANNOT change what linked workflows inherit
|
|
54325
|
+
` + "This tool CANNOT change what linked workflows inherit - prompt, schema, validation rules, notifications and frequency all live in template *versions*, which are immutable snapshots. " + "To change any of those, publish a new version with `create_template_version` (the version IS the edit), then roll it out to linked workflows with `apply_template_version`. " + "There is no in-place edit of a published version, and never report a prompt or schema change as impossible - versioning is the supported path.",
|
|
54124
54326
|
inputSchema: strictSchema({
|
|
54125
54327
|
templateId: exports_external.string().describe("The template ID to update"),
|
|
54126
54328
|
name: exports_external.preprocess(coerceNull(), exports_external.string().optional()).optional().describe("New template name"),
|
|
@@ -54176,7 +54378,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54176
54378
|
}))).optional().describe("Predefined categories for a CLASSIFICATION field ({title, definition}[]). Required for fieldType=CLASSIFICATION; omitted otherwise.")
|
|
54177
54379
|
};
|
|
54178
54380
|
server.registerTool("create_template_version", {
|
|
54179
|
-
description: `Publish a new version of a template. Versions capture the full workflow config: prompt, schema, and notifications. All fields are optional
|
|
54381
|
+
description: `Publish a new version of a template. Versions capture the full workflow config: prompt, schema, and notifications. All fields are optional - include only what this version should set.
|
|
54180
54382
|
|
|
54181
54383
|
` + "THIS IS HOW YOU EDIT A TEMPLATE'S PROMPT OR SCHEMA. Published versions are immutable, so 'changing the template prompt' means publishing a new version here and then calling `apply_template_version` to push it onto linked workflows. " + "`update_template` only renames a template; it cannot touch prompt or schema.",
|
|
54182
54384
|
inputSchema: strictSchema({
|
|
@@ -54185,7 +54387,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54185
54387
|
schemaId: exports_external.string().optional().describe("Existing schema ID to reference (mutually exclusive with schemaFields)"),
|
|
54186
54388
|
schemaFields: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(TemplateSchemaFieldShape).strict())).optional().describe("Inline schema fields to create a new schema (mutually exclusive with schemaId)"),
|
|
54187
54389
|
schemaEntity: exports_external.string().optional().describe("Entity name for the inline schema"),
|
|
54188
|
-
schemaValidationRules: exports_external.preprocess(coerceJson(),
|
|
54390
|
+
schemaValidationRules: exports_external.preprocess(coerceJson(), SchemaValidationRulesSchema).optional().describe('Per-field schema validation rules keyed by field name. Each rule uses kind STRING, NUMBER, OTHER, OBJECT, or ARRAY and nested rules are supported. Rule metadata requires editedBy (default|llm|agent|ops|user) and an ISO-8601 editedAt timestamp. Example: { "price": { "kind": "NUMBER", "minimum": { "value": 0, "editedBy": "user", "editedAt": "2026-01-01T00:00:00.000Z" } } }. Not inherited from prior versions - omitting this on a new version drops any rules the previous version had.'),
|
|
54189
54391
|
notifications: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object({
|
|
54190
54392
|
eventType: exports_external.string().describe("Notification event type"),
|
|
54191
54393
|
eventConfiguration: exports_external.preprocess(coerceJson(), exports_external.record(exports_external.string(), exports_external.unknown())).optional(),
|
|
@@ -54266,7 +54468,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54266
54468
|
return jsonResult({ schemas: schemas4, count: schemas4.length });
|
|
54267
54469
|
}));
|
|
54268
54470
|
server.registerTool("link_template_to_workflows", {
|
|
54269
|
-
description: "Link one or more EXISTING workflows to a template in a single call. " + "This is the bulk equivalent of creating a workflow with `templateId`: linked workflows adopt the template's configuration (prompt, schema, notifications) and stay in sync with it. " + "The template ENFORCES its schema on linked workflows
|
|
54471
|
+
description: "Link one or more EXISTING workflows to a template in a single call. " + "This is the bulk equivalent of creating a workflow with `templateId`: linked workflows adopt the template's configuration (prompt, schema, notifications) and stay in sync with it. " + "The template ENFORCES its schema on linked workflows - their extracted output conforms to the template's declared field names, so this is the way to make many workflows produce a consistent, canonical schema. " + "Use `list_templates`/`get_template` to find the template, and `list_workflows` to find the workflow IDs. " + "Set `force: true` to relink workflows already linked to a different template.",
|
|
54270
54472
|
inputSchema: strictSchema({
|
|
54271
54473
|
templateId: exports_external.string().describe("The template ID to link workflows to"),
|
|
54272
54474
|
workflowIds: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string()).min(1)).describe("Workflow IDs to link to the template (array of strings). Also accepts a single ID string."),
|
|
@@ -54283,7 +54485,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54283
54485
|
return jsonResult({
|
|
54284
54486
|
success: false,
|
|
54285
54487
|
conflicts: result.conflicts,
|
|
54286
|
-
message: `Cannot link
|
|
54488
|
+
message: `Cannot link - ${result.conflicts.length} workflow(s) are already linked to another template: ${summary}. ` + "Re-run with force: true to move them to this template."
|
|
54287
54489
|
});
|
|
54288
54490
|
}
|
|
54289
54491
|
return jsonResult({
|
|
@@ -54343,7 +54545,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54343
54545
|
});
|
|
54344
54546
|
}));
|
|
54345
54547
|
}
|
|
54346
|
-
var SchemaFieldShape, LocationSchema, MonitoringValueOperators, MonitoringValuelessOperators, MonitoringConditionOperatorSchema, MonitoringConditionSchema, MonitoringSchema, RESUMABLE_ASSISTANT_STATUSES, ACTIVE_ASSISTANT_STATUSES, IDLE_ASSISTANT_STATUSES, CLOSED_ASSISTANT_STATUSES, DASHBOARD_BASE_URL = "https://www.kadoa.com", WORKFLOW_AUDIT_WATCHED_KEYS;
|
|
54548
|
+
var SchemaFieldShape, SchemaValidationAttributionShape, SchemaValidationPresenceRule, SchemaValidationUniquenessRule, SchemaValidationStringLengthRule, SchemaValidationStringFormatRule, SchemaValidationFieldRulesSchema, SchemaValidationRulesSchema, LocationSchema, MonitoringValueOperators, MonitoringValuelessOperators, MonitoringConditionOperatorSchema, MonitoringConditionSchema, MonitoringSchema, RESUMABLE_ASSISTANT_STATUSES, ACTIVE_ASSISTANT_STATUSES, IDLE_ASSISTANT_STATUSES, CLOSED_ASSISTANT_STATUSES, DASHBOARD_BASE_URL = "https://www.kadoa.com", WORKFLOW_AUDIT_WATCHED_KEYS;
|
|
54347
54549
|
var init_tools = __esm(() => {
|
|
54348
54550
|
init_dist2();
|
|
54349
54551
|
init_zod();
|
|
@@ -54353,8 +54555,105 @@ var init_tools = __esm(() => {
|
|
|
54353
54555
|
description: exports_external.string().optional().describe("What this field contains"),
|
|
54354
54556
|
example: exports_external.string().describe("Example value"),
|
|
54355
54557
|
dataType: exports_external.enum(["STRING", "NUMBER", "BOOLEAN", "DATE", "DATETIME", "MONEY", "IMAGE", "LINK", "OBJECT", "ARRAY"]).optional().describe("Data type for the field"),
|
|
54356
|
-
isKey: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("Marks this field as a key field
|
|
54558
|
+
isKey: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("Marks this field as a key field - the stable identity used to match records across runs. Change detection diffs records by their key fields, so a monitored or real-time workflow without one cannot tell an updated record from a new one. Set it on whatever uniquely identifies a row (a detail URL, an ID, a ticker).")
|
|
54559
|
+
};
|
|
54560
|
+
SchemaValidationAttributionShape = {
|
|
54561
|
+
editedBy: exports_external.enum(["default", "llm", "agent", "ops", "user"]).describe("Who last edited this rule: default, llm, agent, ops, or user"),
|
|
54562
|
+
editedByLabel: exports_external.string().optional().describe("Optional editor identifier"),
|
|
54563
|
+
editedAt: exports_external.string().datetime().describe("ISO-8601 timestamp when this rule was last edited")
|
|
54357
54564
|
};
|
|
54565
|
+
SchemaValidationPresenceRule = exports_external.object({
|
|
54566
|
+
target: exports_external.number().int().min(0).max(100).step(20).describe("Expected percentage of rows with a value"),
|
|
54567
|
+
...SchemaValidationAttributionShape
|
|
54568
|
+
}).strict();
|
|
54569
|
+
SchemaValidationUniquenessRule = exports_external.object({
|
|
54570
|
+
target: exports_external.number().int().min(0).max(100).step(20).describe("Expected percentage of rows with a unique value"),
|
|
54571
|
+
...SchemaValidationAttributionShape
|
|
54572
|
+
}).strict();
|
|
54573
|
+
SchemaValidationStringLengthRule = exports_external.object({
|
|
54574
|
+
value: exports_external.number().int().min(0).describe("String length bound"),
|
|
54575
|
+
...SchemaValidationAttributionShape
|
|
54576
|
+
}).strict();
|
|
54577
|
+
SchemaValidationStringFormatRule = exports_external.discriminatedUnion("kind", [
|
|
54578
|
+
exports_external.object({
|
|
54579
|
+
kind: exports_external.literal("FREE_TEXT"),
|
|
54580
|
+
charset: exports_external.discriminatedUnion("kind", [
|
|
54581
|
+
exports_external.object({
|
|
54582
|
+
kind: exports_external.literal("PRESET"),
|
|
54583
|
+
preset: exports_external.enum(["natural_language", "alphanumeric", "alpha"])
|
|
54584
|
+
}).strict()
|
|
54585
|
+
]),
|
|
54586
|
+
...SchemaValidationAttributionShape
|
|
54587
|
+
}).strict(),
|
|
54588
|
+
exports_external.object({
|
|
54589
|
+
kind: exports_external.literal("FORMAT"),
|
|
54590
|
+
source: exports_external.discriminatedUnion("kind", [
|
|
54591
|
+
exports_external.object({
|
|
54592
|
+
kind: exports_external.literal("PRESET"),
|
|
54593
|
+
preset: exports_external.enum(["url", "email", "phone", "date", "datetime", "time", "uuid", "slug"])
|
|
54594
|
+
}).strict(),
|
|
54595
|
+
exports_external.object({
|
|
54596
|
+
kind: exports_external.literal("CUSTOM"),
|
|
54597
|
+
pattern: exports_external.string().min(1).describe("Regular expression pattern")
|
|
54598
|
+
}).strict()
|
|
54599
|
+
]),
|
|
54600
|
+
...SchemaValidationAttributionShape
|
|
54601
|
+
}).strict(),
|
|
54602
|
+
exports_external.object({
|
|
54603
|
+
kind: exports_external.literal("LIST"),
|
|
54604
|
+
source: exports_external.discriminatedUnion("kind", [
|
|
54605
|
+
exports_external.object({
|
|
54606
|
+
kind: exports_external.literal("PRESET"),
|
|
54607
|
+
preset: exports_external.enum(["language2", "country2", "country3", "currency3", "month3", "usState2"])
|
|
54608
|
+
}).strict(),
|
|
54609
|
+
exports_external.object({
|
|
54610
|
+
kind: exports_external.literal("CUSTOM"),
|
|
54611
|
+
values: exports_external.array(exports_external.string().min(1)).min(1).describe("Allowed string values")
|
|
54612
|
+
}).strict()
|
|
54613
|
+
]),
|
|
54614
|
+
...SchemaValidationAttributionShape
|
|
54615
|
+
}).strict()
|
|
54616
|
+
]);
|
|
54617
|
+
SchemaValidationFieldRulesSchema = exports_external.lazy(() => exports_external.discriminatedUnion("kind", [
|
|
54618
|
+
exports_external.object({
|
|
54619
|
+
kind: exports_external.literal("STRING"),
|
|
54620
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54621
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54622
|
+
minLength: SchemaValidationStringLengthRule.optional(),
|
|
54623
|
+
maxLength: SchemaValidationStringLengthRule.optional(),
|
|
54624
|
+
minHtmlElements: SchemaValidationStringLengthRule.optional(),
|
|
54625
|
+
maxHtmlElements: SchemaValidationStringLengthRule.optional(),
|
|
54626
|
+
format: SchemaValidationStringFormatRule.optional()
|
|
54627
|
+
}).strict(),
|
|
54628
|
+
exports_external.object({
|
|
54629
|
+
kind: exports_external.literal("NUMBER"),
|
|
54630
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54631
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54632
|
+
minimum: exports_external.object({ value: exports_external.number().describe("Minimum numeric value"), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54633
|
+
maximum: exports_external.object({ value: exports_external.number().describe("Maximum numeric value"), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54634
|
+
maxDecimalPlaces: exports_external.object({ value: exports_external.number().int().min(0).max(16), ...SchemaValidationAttributionShape }).strict().optional()
|
|
54635
|
+
}).strict(),
|
|
54636
|
+
exports_external.object({
|
|
54637
|
+
kind: exports_external.literal("OTHER"),
|
|
54638
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54639
|
+
uniqueness: SchemaValidationUniquenessRule.optional()
|
|
54640
|
+
}).strict(),
|
|
54641
|
+
exports_external.object({
|
|
54642
|
+
kind: exports_external.literal("OBJECT"),
|
|
54643
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54644
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54645
|
+
properties: exports_external.record(exports_external.string(), SchemaValidationFieldRulesSchema)
|
|
54646
|
+
}).strict(),
|
|
54647
|
+
exports_external.object({
|
|
54648
|
+
kind: exports_external.literal("ARRAY"),
|
|
54649
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54650
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54651
|
+
minItems: exports_external.object({ value: exports_external.number().int().min(0), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54652
|
+
maxItems: exports_external.object({ value: exports_external.number().int().min(0), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54653
|
+
items: SchemaValidationFieldRulesSchema.optional()
|
|
54654
|
+
}).strict()
|
|
54655
|
+
]));
|
|
54656
|
+
SchemaValidationRulesSchema = exports_external.record(exports_external.string(), SchemaValidationFieldRulesSchema);
|
|
54358
54657
|
LocationSchema = exports_external.object({
|
|
54359
54658
|
type: exports_external.enum(["auto", "manual"]),
|
|
54360
54659
|
isoCode: exports_external.string().trim().min(2).optional()
|
|
@@ -54443,7 +54742,7 @@ var package_default;
|
|
|
54443
54742
|
var init_package = __esm(() => {
|
|
54444
54743
|
package_default = {
|
|
54445
54744
|
name: "@kadoa/mcp",
|
|
54446
|
-
version: "0.5.
|
|
54745
|
+
version: "0.5.21",
|
|
54447
54746
|
description: "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
|
|
54448
54747
|
type: "module",
|
|
54449
54748
|
main: "dist/index.js",
|
|
@@ -54467,7 +54766,7 @@ var init_package = __esm(() => {
|
|
|
54467
54766
|
prepublishOnly: "bun run check-types && bun run test:unit && bun run build"
|
|
54468
54767
|
},
|
|
54469
54768
|
dependencies: {
|
|
54470
|
-
"@kadoa/node-sdk": "^0.
|
|
54769
|
+
"@kadoa/node-sdk": "^0.38.0",
|
|
54471
54770
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
54472
54771
|
express: "^5.2.1",
|
|
54473
54772
|
"express-rate-limit": "^8.2.1",
|
|
@@ -60046,21 +60345,22 @@ async function createServer(auth, options) {
|
|
|
60046
60345
|
const server = new McpServer({ name: "kadoa", version: package_default.version }, {
|
|
60047
60346
|
instructions: [
|
|
60048
60347
|
"IMPORTANT: One workflow = one source. A single workflow can extract many different fields, tables, and sections from the same URL(s) using a rich schema.",
|
|
60049
|
-
"Do NOT create multiple workflows for different data points on the same page
|
|
60348
|
+
"Do NOT create multiple workflows for different data points on the same page - instead, define one workflow with a multi-field schema covering everything needed.",
|
|
60050
60349
|
"",
|
|
60051
60350
|
"Kadoa workflows use agentic navigation: the AI agent can browse pages, click buttons, fill forms, select dropdowns, paginate, open detail pages, and handle multi-step interactions.",
|
|
60052
60351
|
"Describe the full navigation steps in the prompt (e.g., 'select year 2022 from the dropdown, click Search, extract the table, then repeat for 2023').",
|
|
60053
60352
|
"",
|
|
60054
|
-
"Workflow lifecycle: create_workflow \u2192 get_workflow (check status) \u2192 fetch_data (get results). Workflows run asynchronously
|
|
60353
|
+
"Workflow lifecycle: create_workflow \u2192 get_workflow (check status) \u2192 fetch_data (get results). Workflows run asynchronously - never poll or sleep-wait.",
|
|
60055
60354
|
"",
|
|
60056
|
-
"Use create_realtime_monitor only when the user wants continuous change detection with alerts.
|
|
60057
|
-
"Use scrape for an immediate raw HTML or markdown fetch from one URL. Use create_workflow for structured extraction, recurring runs, monitoring, or navigation-heavy jobs.",
|
|
60058
|
-
"
|
|
60355
|
+
"Use create_realtime_monitor only when the user wants continuous Julie change detection with alerts. It first persists notification channels, then asynchronously returns workflow/session/thread/job IDs; use the workflow Assistant tools for follow-up status, questions, and controls.",
|
|
60356
|
+
"For one-time or scheduled extraction, use create_workflow. Use scrape for an immediate raw HTML or markdown fetch from one URL. Use create_workflow for structured extraction, recurring runs, monitoring, or navigation-heavy jobs.",
|
|
60357
|
+
"If a one-time or scheduled workflow fails, retry it with run_workflow using the existing workflow ID. Do NOT delete and recreate the workflow just to retry it - preserve its workflow ID and configuration. Realtime workflows cannot be manually run.",
|
|
60358
|
+
"Use list_changes and get_change to retrieve detected diffs from realtime monitoring workflows.",
|
|
60059
60359
|
"",
|
|
60060
60360
|
"Schema tips: Use descriptive field names and examples. Group related data under one entity.",
|
|
60061
|
-
"The AI agent uses the schema + prompt to understand what to extract
|
|
60361
|
+
"The AI agent uses the schema + prompt to understand what to extract - a detailed prompt with a comprehensive schema produces better results than multiple simple workflows.",
|
|
60062
60362
|
"",
|
|
60063
|
-
"Templates enforce their schema: a workflow created from a template (create_workflow with templateId) or linked to one (link_template_to_workflows) produces output whose field names conform to the template's declared schema. Use templates when you need many workflows to return a consistent, canonical set of fields
|
|
60363
|
+
"Templates enforce their schema: a workflow created from a template (create_workflow with templateId) or linked to one (link_template_to_workflows) produces output whose field names conform to the template's declared schema. Use templates when you need many workflows to return a consistent, canonical set of fields - do NOT assume the extractor will drift field names away from a template's schema."
|
|
60064
60364
|
].join(`
|
|
60065
60365
|
`)
|
|
60066
60366
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kadoa/mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.21",
|
|
4
4
|
"description": "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"prepublishOnly": "bun run check-types && bun run test:unit && bun run build"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@kadoa/node-sdk": "^0.
|
|
27
|
+
"@kadoa/node-sdk": "^0.38.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
29
29
|
"express": "^5.2.1",
|
|
30
30
|
"express-rate-limit": "^8.2.1",
|