@daeda/mcp-pro 0.1.53 → 0.1.54

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.
Files changed (2) hide show
  1. package/dist/index.js +112 -197
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -84095,36 +84095,6 @@ async function deleteRowsForObjectTypes(connection, tableName, objectTypes) {
84095
84095
  );
84096
84096
  }
84097
84097
  }
84098
- async function readPropertyDefinitionStatesForTypes(connection, objectTypes) {
84099
- if (objectTypes.length === 0) {
84100
- return /* @__PURE__ */ new Map();
84101
- }
84102
- const states = /* @__PURE__ */ new Map();
84103
- for (const batch of chunk([...objectTypes], DELETE_BATCH_SIZE)) {
84104
- const reader = await connection.runAndReadAll(
84105
- `SELECT object_type, object_type_id, fingerprint, property_count, group_count, last_checked_at, last_changed_at, status, error
84106
- FROM property_definition_object_state
84107
- WHERE object_type IN (${buildSqlPlaceholders(batch.length)})`,
84108
- batch
84109
- );
84110
- const rows = reader.getRowObjects();
84111
- for (const row of rows) {
84112
- const parsed = PROPERTY_DEFINITION_OBJECT_STATE_ROW_SCHEMA.parse({
84113
- objectType: row.object_type,
84114
- objectTypeId: row.object_type_id,
84115
- fingerprint: row.fingerprint,
84116
- propertyCount: typeof row.property_count === "number" ? row.property_count : Number(row.property_count ?? 0),
84117
- groupCount: typeof row.group_count === "number" ? row.group_count : Number(row.group_count ?? 0),
84118
- lastCheckedAt: row.last_checked_at,
84119
- lastChangedAt: row.last_changed_at,
84120
- status: row.status,
84121
- error: row.error ?? null
84122
- });
84123
- states.set(parsed.objectType, parsed);
84124
- }
84125
- }
84126
- return states;
84127
- }
84128
84098
  async function replacePropertyDefinitionSlices(connection, objectTypes, propertyDefinitions, propertyGroups, objectStates) {
84129
84099
  await deleteRowsForObjectTypes(connection, "property_definitions", objectTypes);
84130
84100
  await deleteRowsForObjectTypes(connection, "property_groups", objectTypes);
@@ -84254,108 +84224,6 @@ async function syncAssociationSchemaSnapshot({
84254
84224
  });
84255
84225
  return { portalId };
84256
84226
  }
84257
- async function syncPropertyDefinitionsSnapshot({
84258
- masterLock,
84259
- portalId,
84260
- snapshot
84261
- }) {
84262
- assertWritable(masterLock);
84263
- const handle = await getDatabaseConnection(portalId, null);
84264
- const parsedSnapshot = PROPERTY_DEFINITIONS_SNAPSHOT_SCHEMA.parse(snapshot);
84265
- await initializeDb(handle.connection);
84266
- await ensureDataPluginSchema(handle.connection, "property-definitions");
84267
- await withTransaction(handle.connection, async () => {
84268
- await ensureTable(handle.connection, PROPERTY_DEFINITIONS_TABLE_STATEMENTS);
84269
- const skippedObjectTypes = new Set(
84270
- parsedSnapshot.partial?.skippedObjects.map((item) => item.objectType) ?? []
84271
- );
84272
- if (skippedObjectTypes.size === 0) {
84273
- await replacePluginTable(
84274
- handle.connection,
84275
- /* @__PURE__ */ new Set([
84276
- "property_definitions",
84277
- "property_groups",
84278
- "property_definition_object_state"
84279
- ]),
84280
- "property_definitions",
84281
- propertyDefinitionRowsToColumns(parsedSnapshot.propertyDefinitions)
84282
- );
84283
- await replacePluginTable(
84284
- handle.connection,
84285
- /* @__PURE__ */ new Set([
84286
- "property_definitions",
84287
- "property_groups",
84288
- "property_definition_object_state"
84289
- ]),
84290
- "property_groups",
84291
- propertyGroupRowsToColumns(parsedSnapshot.propertyGroups)
84292
- );
84293
- await replacePluginTable(
84294
- handle.connection,
84295
- /* @__PURE__ */ new Set([
84296
- "property_definitions",
84297
- "property_groups",
84298
- "property_definition_object_state"
84299
- ]),
84300
- "property_definition_object_state",
84301
- propertyDefinitionObjectStateRowsToColumns(parsedSnapshot.objectStates)
84302
- );
84303
- return;
84304
- }
84305
- const includedObjectTypes = [
84306
- ...new Set(parsedSnapshot.objectStates.map((row) => row.objectType))
84307
- ].filter((objectType) => !skippedObjectTypes.has(objectType));
84308
- const existingSkippedStates = await readPropertyDefinitionStatesForTypes(
84309
- handle.connection,
84310
- parsedSnapshot.partial?.skippedObjects.map((item) => item.objectType) ?? []
84311
- );
84312
- const mergedObjectStates = parsedSnapshot.objectStates.map((row) => {
84313
- if (!skippedObjectTypes.has(row.objectType)) {
84314
- return row;
84315
- }
84316
- const existing = existingSkippedStates.get(row.objectType);
84317
- if (!existing) {
84318
- return row;
84319
- }
84320
- return {
84321
- ...existing,
84322
- objectTypeId: row.objectTypeId,
84323
- lastCheckedAt: row.lastCheckedAt,
84324
- status: row.status,
84325
- error: row.error
84326
- };
84327
- });
84328
- await replacePropertyDefinitionSlices(
84329
- handle.connection,
84330
- includedObjectTypes,
84331
- parsedSnapshot.propertyDefinitions.filter(
84332
- (row) => !skippedObjectTypes.has(row.objectType)
84333
- ),
84334
- parsedSnapshot.propertyGroups.filter(
84335
- (row) => !skippedObjectTypes.has(row.objectType)
84336
- ),
84337
- mergedObjectStates.filter(
84338
- (row) => !skippedObjectTypes.has(row.objectType)
84339
- )
84340
- );
84341
- const skippedStates = mergedObjectStates.filter(
84342
- (row) => skippedObjectTypes.has(row.objectType)
84343
- );
84344
- if (skippedStates.length > 0) {
84345
- await deleteRowsForObjectTypes(
84346
- handle.connection,
84347
- "property_definition_object_state",
84348
- skippedStates.map((row) => row.objectType)
84349
- );
84350
- await bulkAppend(
84351
- handle.connection,
84352
- "property_definition_object_state",
84353
- propertyDefinitionObjectStateRowsToColumns(skippedStates)
84354
- );
84355
- }
84356
- });
84357
- return { portalId };
84358
- }
84359
84227
  async function applyWorkflowDelta({
84360
84228
  masterLock,
84361
84229
  portalId,
@@ -85421,23 +85289,6 @@ var DuckDBInterfaceLiveBase = Layer4.effect(
85421
85289
  }))
85422
85290
  )
85423
85291
  );
85424
- const syncPropertyDefinitionsSnapshot2 = (input) => withPortalWritePermit(
85425
- input.portalId,
85426
- "syncPropertyDefinitionsSnapshot",
85427
- Effect32.orDie(
85428
- syncReplicaAfterWrite({
85429
- portalId: input.portalId,
85430
- reason: "syncPropertyDefinitionsSnapshot"
85431
- }, Effect32.tryPromise({
85432
- try: () => syncPropertyDefinitionsSnapshot({
85433
- masterLock: { isMaster: true },
85434
- portalId: input.portalId,
85435
- snapshot: input.snapshot
85436
- }),
85437
- catch: (error) => error
85438
- }))
85439
- )
85440
- );
85441
85292
  const applyWorkflowDelta2 = (input) => withPortalWritePermit(
85442
85293
  input.portalId,
85443
85294
  "applyWorkflowDelta",
@@ -85560,7 +85411,6 @@ var DuckDBInterfaceLiveBase = Layer4.effect(
85560
85411
  syncPlugin: syncPlugin2,
85561
85412
  replaceWorkflowRows: replaceWorkflowRows2,
85562
85413
  syncAssociationSchemaSnapshot: syncAssociationSchemaSnapshot2,
85563
- syncPropertyDefinitionsSnapshot: syncPropertyDefinitionsSnapshot2,
85564
85414
  applyWorkflowDelta: applyWorkflowDelta2,
85565
85415
  applyPropertyDefinitionsDelta: applyPropertyDefinitionsDelta2,
85566
85416
  applyDiffBatch: applyDiffBatch2,
@@ -87095,36 +86945,6 @@ var PortalDataLiveBase = Layer7.effect(
87095
86945
  )
87096
86946
  )
87097
86947
  );
87098
- const syncPropertyDefinitionsSnapshot2 = (input) => pipe27(
87099
- requireMasterConnection(input.portalId, "syncPropertyDefinitionsSnapshot"),
87100
- Effect39.flatMap(
87101
- () => pipe27(
87102
- duckDb.syncPropertyDefinitionsSnapshot({
87103
- portalId: input.portalId,
87104
- snapshot: input.snapshot
87105
- }),
87106
- Effect39.flatMap(
87107
- () => duckDb.setMetadata(
87108
- input.portalId,
87109
- "last_synced:property_definitions",
87110
- (/* @__PURE__ */ new Date()).toISOString()
87111
- )
87112
- ),
87113
- Effect39.flatMap(
87114
- () => swallowPortalFileStateError(portalFileState.touchSyncedAt(input.portalId))
87115
- ),
87116
- Effect39.map(() => ({
87117
- portalId: input.portalId
87118
- })),
87119
- Effect39.catchAllCause(
87120
- (cause) => toSyncFailure(
87121
- `Failed to sync property definitions snapshot for portal ${input.portalId}`,
87122
- cause
87123
- )
87124
- )
87125
- )
87126
- )
87127
- );
87128
86948
  const applyWorkflowDelta2 = (input) => pipe27(
87129
86949
  requireMasterConnection(input.portalId, "applyWorkflowDelta"),
87130
86950
  Effect39.flatMap(
@@ -87258,7 +87078,6 @@ var PortalDataLiveBase = Layer7.effect(
87258
87078
  syncPluginPayload,
87259
87079
  replaceWorkflowRows: replaceWorkflowRows2,
87260
87080
  syncAssociationSchemaSnapshot: syncAssociationSchemaSnapshot2,
87261
- syncPropertyDefinitionsSnapshot: syncPropertyDefinitionsSnapshot2,
87262
87081
  applyWorkflowDelta: applyWorkflowDelta2,
87263
87082
  applyPropertyDefinitionsDelta: applyPropertyDefinitionsDelta2,
87264
87083
  applyDiffBatch: applyDiffBatch2,
@@ -88883,7 +88702,9 @@ Optional: pass portalIds to run the same query across one or more specific porta
88883
88702
 
88884
88703
  Data freshness: enabled portals are automatically checked for freshness before querying. If portal sync is disabled, queries use stale local data when available and otherwise return an error.
88885
88704
 
88886
- Lightweight message-plugin metadata can still be stale even when the portal is otherwise synced. Use \`status\` to inspect plugin freshness and \`refresh_plugins\` to explicitly refresh lightweight plugin tables like lists or owners when you need the latest values.
88705
+ IMPORTANT: the automatic freshness check covers artifact-backed CRM data, but it does NOT make lightweight message-plugin tables current. Before querying plugin-backed tables such as lists, owners, pipelines, forms, inboxes, or sequences when current values matter, first inspect status(section="schema"), call refresh_plugins if needed, and wait for completion via status(section="schema") before running the query.
88706
+
88707
+ If your task depends on both artifact-backed data and plugin-backed metadata, refresh the plugin data first, wait for completion, then run the query.
88887
88708
 
88888
88709
  IMPORTANT: Always use the 'status' tool with section "schema" first to discover available object types and property names before writing queries. Do not guess property names.
88889
88710
 
@@ -89246,7 +89067,7 @@ Optional: pass portalIds to run the same chart query across one or more specific
89246
89067
 
89247
89068
  Data freshness: enabled portals are automatically checked for freshness before charting. If portal sync is disabled, charting uses stale local data when available and otherwise returns an error.
89248
89069
 
89249
- Lightweight message-plugin metadata can still be stale even when the portal is otherwise synced. Use \`status\` to inspect plugin freshness and \`refresh_plugins\` to explicitly refresh lightweight plugin tables like lists or owners when you need the latest values.
89070
+ IMPORTANT: the automatic freshness check covers artifact-backed CRM data, but it does NOT automatically refresh lightweight message-plugin tables. Before charting plugin-backed tables such as lists, owners, pipelines, forms, inboxes, or sequences when current values matter, first inspect status(section="schema"), call refresh_plugins if needed, and wait for completion via status(section="schema") before charting.
89250
89071
 
89251
89072
  The query results map to the chart as follows:
89252
89073
  - First column \u2192 X-axis labels (categories)
@@ -89563,6 +89384,10 @@ The schema output also includes lightweight plugin freshness data so you can see
89563
89384
 
89564
89385
  Status output also includes active and recent lightweight plugin refresh jobs so callers can inspect queued, running, completed, or failed manual refresh requests without blocking on the initial tool call.
89565
89386
 
89387
+ Use status(section="schema") as the authoritative freshness gate for lightweight plugins. After calling refresh_plugins, poll status(section="schema") for the same portal until the matching refresh job is COMPLETED, none of the requested plugins are still QUEUED, RUNNING, or REPLICATING, and the requested plugins show updated lastRefreshedAt values. Do not proceed with plugin-dependent work before those conditions are met.
89388
+
89389
+ Artifact-backed CRM data and lightweight plugin metadata have different freshness rules. Artifact freshness is handled automatically for query/chart reads, but lightweight plugin freshness is not.
89390
+
89566
89391
  Optional: pass portalIds to fetch schema status for specific portals. When portalIds is provided, schema output is a JSON object keyed by portal ID.
89567
89392
 
89568
89393
  Data readiness: only portals with sync enabled are refreshed automatically. Disabled portals can still report schema from stale local data if a local DB already exists.
@@ -133956,6 +133781,8 @@ VIEWING THE PLAN:
133956
133781
 
133957
133782
  IMPORTANT: After building the plan, present it to the user and ask for confirmation before calling submit_plan.
133958
133783
 
133784
+ When building operations that depend on current lightweight metadata or IDs from local tables, such as owners, lists, pipelines, forms, inboxes, or sequences, first ensure those plugin tables are fresh. Use status(section="schema") to inspect freshness, refresh_plugins to refresh the required plugin set, and wait for completion with status(section="schema") before resolving IDs or constructing operations that depend on them.
133785
+
133959
133786
  WORKFLOW:
133960
133787
  1. describe_operations - Discover available operation types and their required fields
133961
133788
  2. build_plan - Create draft with title, description, and operations
@@ -134614,11 +134441,17 @@ function registerRefreshPluginsTool(server2, deps) {
134614
134441
 
134615
134442
  Lightweight plugins are not kept fresh automatically in real time. Their data may become stale until you explicitly refresh them with this tool.
134616
134443
 
134617
- Use this when you need the latest lightweight metadata, such as lists, owners, pipelines, forms, inboxes, or other message-backed plugin data.
134444
+ Use this when you need current lightweight metadata, such as lists, owners, pipelines, forms, inboxes, sequences, or other message-backed plugin data.
134445
+
134446
+ Before calling this tool, first determine the full set of plugin-backed metadata you will need for the task. Prefer a single refresh_plugins call with the union of all needed pluginNames rather than separate calls per plugin.
134618
134447
 
134619
134448
  The requested pluginNames array is required. Optional portalIds lets you refresh the same plugins across multiple portals; otherwise the selected portal is used.
134620
134449
 
134621
- This tool returns immediately with a refresh job record instead of blocking until the refresh completes. Use \`status\` to inspect in-flight and recent refresh jobs.`,
134450
+ This tool starts an asynchronous refresh job and returns immediately. It does NOT wait for fresh data to be available.
134451
+
134452
+ After calling refresh_plugins, do not run any query, chart, or plan-building step that depends on those plugin tables until you confirm completion with status(section="schema"). Wait until the relevant refresh job is COMPLETED and the requested plugins show updated freshness data. If the job FAILED, surface the error instead of proceeding.
134453
+
134454
+ If the same plugin set is needed across multiple portals, prefer one call using portalIds. Use \`status\` to inspect in-flight and recent refresh jobs.`,
134622
134455
  inputSchema: {
134623
134456
  pluginNames: z97.array(z97.string()).min(1).describe("Required lightweight plugin names to refresh, for example ['lists', 'owners']."),
134624
134457
  portalIds: z97.array(z97.number()).optional().describe("Optional explicit portal IDs to refresh. If omitted, the selected portal is used.")
@@ -134793,7 +134626,7 @@ var createPluginRefreshJobStore = () => {
134793
134626
  error: payload.error ?? null,
134794
134627
  coalescedRequests: 0,
134795
134628
  plugins: buildPluginSnapshots(pluginNames),
134796
- active: payload.status === "QUEUED" || payload.status === "RUNNING"
134629
+ active: payload.status === "QUEUED" || payload.status === "RUNNING" || payload.status === "REPLICATING"
134797
134630
  };
134798
134631
  job.portalId = payload.target_portal;
134799
134632
  job.pluginNames = pluginNames;
@@ -134803,7 +134636,7 @@ var createPluginRefreshJobStore = () => {
134803
134636
  job.startedAt = payload.started_at ?? job.startedAt ?? null;
134804
134637
  job.finishedAt = payload.finished_at ?? (payload.status === "COMPLETED" || payload.status === "FAILED" ? (/* @__PURE__ */ new Date()).toISOString() : null);
134805
134638
  job.error = payload.error ?? null;
134806
- job.active = payload.status === "QUEUED" || payload.status === "RUNNING";
134639
+ job.active = payload.status === "QUEUED" || payload.status === "RUNNING" || payload.status === "REPLICATING";
134807
134640
  const pluginMap = new Map(job.plugins.map((plugin) => [plugin.pluginName, plugin]));
134808
134641
  for (const pluginName of pluginNames) {
134809
134642
  if (!pluginMap.has(pluginName)) {
@@ -134897,6 +134730,52 @@ var createPluginRefreshJobStore = () => {
134897
134730
  };
134898
134731
  };
134899
134732
 
134733
+ // src/pure/manual-plugin-refresh-job.ts
134734
+ var earliestStartedAt = (plugins2) => plugins2.map((plugin) => plugin.startedAt).filter((value) => value !== null).sort()[0] ?? null;
134735
+ var finalizeManualPluginRefreshJob = async (input) => {
134736
+ const startedAt = earliestStartedAt(input.plugins);
134737
+ await input.updateJobProgress({
134738
+ jobId: input.jobId,
134739
+ portalId: input.portalId,
134740
+ pluginNames: input.pluginNames,
134741
+ createdAt: input.createdAt,
134742
+ status: "REPLICATING",
134743
+ plugins: input.plugins,
134744
+ startedAt,
134745
+ relayToServer: input.relayToServer
134746
+ });
134747
+ try {
134748
+ await input.publishReplica();
134749
+ } catch (error) {
134750
+ const message = input.formatError(error);
134751
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
134752
+ await input.updateJobProgress({
134753
+ jobId: input.jobId,
134754
+ portalId: input.portalId,
134755
+ pluginNames: input.pluginNames,
134756
+ createdAt: input.createdAt,
134757
+ status: "FAILED",
134758
+ plugins: input.plugins,
134759
+ startedAt,
134760
+ finishedAt,
134761
+ error: message,
134762
+ relayToServer: input.relayToServer
134763
+ });
134764
+ return;
134765
+ }
134766
+ await input.updateJobProgress({
134767
+ jobId: input.jobId,
134768
+ portalId: input.portalId,
134769
+ pluginNames: input.pluginNames,
134770
+ createdAt: input.createdAt,
134771
+ status: "COMPLETED",
134772
+ plugins: input.plugins,
134773
+ startedAt,
134774
+ finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
134775
+ relayToServer: input.relayToServer
134776
+ });
134777
+ };
134778
+
134900
134779
  // src/effects/ensure-fresh.ts
134901
134780
  import fs20 from "fs";
134902
134781
  var DEFAULT_QUEUE_DRAIN_TIMEOUT_MS = 12e4;
@@ -135595,17 +135474,56 @@ var mainProgram = Effect147.gen(function* () {
135595
135474
  const allDone = plugins2.every(
135596
135475
  (plugin) => plugin.status === "SYNCED" || plugin.status === "PARTIAL" || plugin.status === "FAILED"
135597
135476
  );
135598
- await updateJobProgress({
135477
+ if (!allDone) {
135478
+ await updateJobProgress({
135479
+ jobId: input.jobId,
135480
+ portalId: input.portalId,
135481
+ pluginNames: input.pluginNames,
135482
+ createdAt: input.createdAt,
135483
+ status: "RUNNING",
135484
+ plugins: plugins2,
135485
+ startedAt: plugins2.map((plugin) => plugin.startedAt).filter((value) => value !== null).sort()[0] ?? null,
135486
+ relayToServer: input.relayToServer
135487
+ });
135488
+ return;
135489
+ }
135490
+ if (hasFailure) {
135491
+ await updateJobProgress({
135492
+ jobId: input.jobId,
135493
+ portalId: input.portalId,
135494
+ pluginNames: input.pluginNames,
135495
+ createdAt: input.createdAt,
135496
+ status: "FAILED",
135497
+ plugins: plugins2,
135498
+ startedAt: plugins2.map((plugin) => plugin.startedAt).filter((value) => value !== null).sort()[0] ?? null,
135499
+ finishedAt: now,
135500
+ error: plugins2.find((plugin) => plugin.status === "FAILED")?.error ?? null,
135501
+ relayToServer: input.relayToServer
135502
+ });
135503
+ return;
135504
+ }
135505
+ await finalizeManualPluginRefreshJob({
135599
135506
  jobId: input.jobId,
135600
135507
  portalId: input.portalId,
135601
135508
  pluginNames: input.pluginNames,
135602
135509
  createdAt: input.createdAt,
135603
- status: allDone ? hasFailure ? "FAILED" : "COMPLETED" : "RUNNING",
135604
135510
  plugins: plugins2,
135605
- startedAt: plugins2.map((plugin) => plugin.startedAt).filter((value) => value !== null).sort()[0] ?? null,
135606
- finishedAt: allDone ? now : null,
135607
- error: hasFailure ? plugins2.find((plugin) => plugin.status === "FAILED")?.error ?? null : null,
135608
- relayToServer: input.relayToServer
135511
+ relayToServer: input.relayToServer,
135512
+ updateJobProgress,
135513
+ publishReplica: () => Effect147.runPromise(
135514
+ pipe122(
135515
+ ReplicaService,
135516
+ Effect147.flatMap(
135517
+ (replica) => replica.syncReplica({
135518
+ portalId: input.portalId,
135519
+ reason: `manualPluginRefresh:${input.jobId}`,
135520
+ mode: "immediate"
135521
+ })
135522
+ ),
135523
+ Effect147.provide(ReplicaLive)
135524
+ )
135525
+ ),
135526
+ formatError: formatErrorMessage2
135609
135527
  });
135610
135528
  }
135611
135529
  });
@@ -135796,11 +135714,8 @@ var mainProgram = Effect147.gen(function* () {
135796
135714
  const workflowsArtifactReady = portalState?.artifacts.some(
135797
135715
  (artifact) => artifact.object_type === "workflows" && isArtifactBaselineReady(artifact.status)
135798
135716
  ) ?? false;
135799
- const propertyDefinitionsArtifactReady = portalState?.artifacts.some(
135800
- (artifact) => artifact.object_type === "property_definitions" && isArtifactBaselineReady(artifact.status)
135801
- ) ?? false;
135802
135717
  const workflowBaselineReady = workflowStateResult.readable && (workflowLastSyncedAt !== null || workflowsArtifactReady);
135803
- const propertyDefinitionBaselineReady = propertyDefinitionStateResult.readable && (propertyDefinitionLastSyncedAt !== null || propertyDefinitionsArtifactReady);
135718
+ const propertyDefinitionBaselineReady = propertyDefinitionStateResult.readable && propertyDefinitionLastSyncedAt !== null;
135804
135719
  return {
135805
135720
  clientUuid: clientState.clientUuid,
135806
135721
  portalId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daeda/mcp-pro",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "description": "MCP server for HubSpot CRM — sync, query, and manage your portal data",
5
5
  "type": "module",
6
6
  "bin": {