node-autotask 0.21.0 → 0.23.0

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 (56) hide show
  1. package/ARCHITECTURE.md +44 -21
  2. package/CHANGELOG.md +31 -0
  3. package/MCP_TOOL_CATALOG.json +69 -10
  4. package/MCP_TOOL_MANIFEST.md +20 -17
  5. package/MCP_TOOL_OVERRIDES.json +6 -6
  6. package/N8N_MCP_MANIFEST.json +20 -4
  7. package/N8N_MCP_MANIFEST.md +6 -5
  8. package/README.md +9 -9
  9. package/capabilities.json +2898 -7412
  10. package/capabilities.schema.json +0 -12
  11. package/dist/capabilities.cjs +2 -2
  12. package/dist/capabilities.d.cts +0 -2
  13. package/dist/capabilities.d.ts +0 -2
  14. package/dist/capabilities.js +1 -1
  15. package/dist/{chunk-KD6LOSAK.js → chunk-B5SNZ3TZ.js} +3473 -3084
  16. package/dist/{chunk-QWAWNQEZ.cjs → chunk-D5TVBI4U.cjs} +3021 -2632
  17. package/dist/{chunk-CBUY3MKB.cjs → chunk-JUO3URUI.cjs} +2897 -7411
  18. package/dist/{chunk-HEW4WJLC.cjs → chunk-N27NUB4R.cjs} +2466 -1745
  19. package/dist/{chunk-DM67SXCO.js → chunk-OGNUI3UR.js} +2897 -7411
  20. package/dist/{chunk-GBVUXAUA.js → chunk-PVUUOM5G.js} +2092 -1371
  21. package/dist/{chunk-PMPFQDVM.cjs → chunk-TTQB537V.cjs} +135 -135
  22. package/dist/{chunk-JRSU6PKP.js → chunk-VYFO2N5F.js} +2 -2
  23. package/dist/{index-BXtKN1M5.d.cts → index-BVtycq-6.d.cts} +1 -1
  24. package/dist/{index-BXtKN1M5.d.ts → index-BVtycq-6.d.ts} +1 -1
  25. package/dist/{index-DSnuyiTr.d.ts → index-DBoX-Dnk.d.ts} +430 -957
  26. package/dist/{index-ByWYfNog.d.cts → index-NC-x-bYl.d.cts} +430 -957
  27. package/dist/index.cjs +91 -62
  28. package/dist/index.d.cts +360 -5
  29. package/dist/index.d.ts +360 -5
  30. package/dist/index.js +74 -45
  31. package/dist/operations/index.cjs +462 -462
  32. package/dist/operations/index.d.cts +78 -84
  33. package/dist/operations/index.d.ts +78 -84
  34. package/dist/operations/index.js +382 -382
  35. package/dist/pool.cjs +8 -8
  36. package/dist/pool.d.cts +2 -2
  37. package/dist/pool.d.ts +2 -2
  38. package/dist/pool.js +4 -4
  39. package/dist/resources/index.cjs +4 -4
  40. package/dist/resources/index.d.cts +2 -2
  41. package/dist/resources/index.d.ts +2 -2
  42. package/dist/resources/index.js +3 -3
  43. package/dist/types/index.d.cts +1 -1
  44. package/dist/types/index.d.ts +1 -1
  45. package/docs/API.md +133 -41
  46. package/docs/N8N-ADAPTER.md +3 -3
  47. package/examples/mcp/errors.ts +135 -0
  48. package/examples/mcp/manifest.ts +168 -0
  49. package/examples/mcp/register.ts +66 -0
  50. package/examples/mcp/schemas.ts +203 -0
  51. package/examples/mcp/tools-meta.ts +120 -0
  52. package/examples/mcp/tools-mode.ts +177 -0
  53. package/examples/mcp/tools-read.ts +264 -0
  54. package/examples/mcp/types.ts +34 -0
  55. package/examples/mcp-register.ts +9 -1074
  56. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
- import { a as AutotaskClient, f4 as BlindSurfaceInfo, f5 as RelationshipResource, f6 as BlindSurfaceInventory, f7 as BlindSurfaceRow, f8 as CreateBlockerKind, f9 as CreateGuidanceReport, fa as FieldCacheKind, g as AutotaskConfigError } from '../index-ByWYfNog.cjs';
2
- export { fb as FIELD_CACHE_KINDS } from '../index-ByWYfNog.cjs';
3
- import { I as Identifier, cE as EmptyReasonInfo, dI as PickListValue, a as FilterCondition } from '../index-BXtKN1M5.cjs';
4
- export { hp as PICKLIST_VALUE_NOT_SERVED_NOTE } from '../index-BXtKN1M5.cjs';
1
+ import { a as AutotaskClient, ea as BlindSurfaceInfo, eb as RelationshipResource, ec as BlindSurfaceInventory, ed as BlindSurfaceRow, ee as CreateBlockerKind, ef as CreateGuidanceReport, Z as ZoneName, eg as FieldCacheKind, i as AutotaskConfigError } from '../index-NC-x-bYl.cjs';
2
+ export { eh as FIELD_CACHE_KINDS } from '../index-NC-x-bYl.cjs';
3
+ import { I as Identifier, cG as EmptyReasonInfo, dI as PickListValue, a as FilterCondition } from '../index-BVtycq-6.cjs';
4
+ export { hp as PICKLIST_VALUE_NOT_SERVED_NOTE } from '../index-BVtycq-6.cjs';
5
5
  import { CapabilityRecord } from '../capabilities.cjs';
6
6
 
7
7
  /**
@@ -20,8 +20,10 @@ declare const WORKFLOW_RESOURCES: readonly string[];
20
20
  interface SearchAcrossResourcesOptions {
21
21
  /** Resource keys to search (default: the five workflow resources). */
22
22
  resources?: readonly string[];
23
- /** Max matches per resource (default 25, max 500). */
23
+ /** Max matches PER RESOURCE (default 25, max 500) — a sweep over N resources can return up to N x limit matches; use `totalLimit` to cap the whole sweep. */
24
24
  limit?: number;
25
+ /** Optional cap on matches ACROSS ALL resources (positive integer). Resources are searched in request order, each asked for `min(limit, remaining)`; once the cap is met the remaining resources are not queried and are listed in `notSearched`. Absent = no cap and the result is unchanged. */
26
+ totalLimit?: number;
25
27
  }
26
28
  /** One searched resource's matches (compact shapes; `Summary = full record`). */
27
29
  interface SearchAcrossResourcesRow {
@@ -35,6 +37,10 @@ interface SearchAcrossResourcesResult {
35
37
  results: SearchAcrossResourcesRow[];
36
38
  /** Requested keys without a `search` helper — skipped and reported, never errored. */
37
39
  skipped: string[];
40
+ /** Only with `totalLimit`: resources that HAVE a `search` helper but were not queried because the cap was already met, in request order. */
41
+ notSearched?: string[];
42
+ /** Only with `totalLimit`: true when more matches may exist — some resource was not searched, or a searched resource returned exactly the quota it was asked for (`min(limit, remaining)`). */
43
+ truncated?: boolean;
38
44
  }
39
45
  /** One fetchMany item: a single-record GET by vendor numeric id. */
40
46
  interface FetchManyItem {
@@ -449,6 +455,68 @@ interface CreateGuidanceOptions {
449
455
  */
450
456
  declare function createGuidance(client: AutotaskClient, opts?: CreateGuidanceOptions): Promise<CreateGuidanceReport>;
451
457
 
458
+ /** entity (plan resource key) -> ExecuteCommand `Code` + id parameter name. */
459
+ declare const ENTITIES: {
460
+ readonly time_entries: {
461
+ readonly code: "EditTimeEntry";
462
+ readonly param: "WorkEntryID";
463
+ };
464
+ readonly tickets: {
465
+ readonly code: "OpenTicketDetail";
466
+ readonly param: "TicketID";
467
+ };
468
+ readonly tasks: {
469
+ readonly code: "OpenTaskDetail";
470
+ readonly param: "TaskID";
471
+ };
472
+ readonly projects: {
473
+ readonly code: "OpenProject";
474
+ readonly param: "ProjectID";
475
+ };
476
+ readonly companies: {
477
+ readonly code: "OpenAccount";
478
+ readonly param: "AccountID";
479
+ };
480
+ readonly contacts: {
481
+ readonly code: "OpenContact";
482
+ readonly param: "ContactID";
483
+ };
484
+ readonly contracts: {
485
+ readonly code: "OpenContract";
486
+ readonly param: "ContractID";
487
+ };
488
+ readonly configuration_items: {
489
+ readonly code: "EditInstalledProduct";
490
+ readonly param: "InstalledProductID";
491
+ };
492
+ };
493
+ type UiLinkEntity = keyof typeof ENTITIES;
494
+ declare const UI_LINK_ENTITIES: UiLinkEntity[];
495
+ /** The input of `buildUiLink` / `operations.uiLink`. */
496
+ interface UiLinkInput {
497
+ /** The plan resource key of the record: one of UI_LINK_ENTITIES. */
498
+ entity: string;
499
+ /** The vendor numeric id (positive safe integer). */
500
+ id?: number;
501
+ /** Tickets only: the displayed ticket number (`T20240101.0001`); exclusive with `id`. */
502
+ ticketNumber?: string;
503
+ /** Explicit UI host (`ww<N>.autotask.net`), overriding derivation. */
504
+ host?: string;
505
+ /** A zone name from the catalog (derives the host the same way as the client base). */
506
+ zone?: ZoneName;
507
+ /** A REST base URL (e.g. the client's) to derive the host from. */
508
+ baseUrl?: string;
509
+ }
510
+ /** Build the deep link, or `undefined` when no UI host can be derived. Throws a typed CONFIG_ERROR on bad input. */
511
+ declare function buildUiLink(input: UiLinkInput): string | undefined;
512
+ /** The `operations.uiLink` result: the URL, or null with the reason no host could be derived. */
513
+ interface UiLinkResult {
514
+ url: string | null;
515
+ reason?: string;
516
+ }
517
+ /** Zero-wire meta op: build the deep link from the client's live REST base (or an explicit `host`). */
518
+ declare function uiLink(client: AutotaskClient, input: UiLinkInput): Promise<UiLinkResult>;
519
+
452
520
  /** The pinned wire cap: `resources × include` above it is refused
453
521
  * pre-request (CONFIG_ERROR naming the computed cost and the cap) —
454
522
  * refused, never truncated. */
@@ -762,82 +830,6 @@ interface RecoveryOptions {
762
830
  */
763
831
  declare function recovery(client: AutotaskClient, input: RecoveryInput, opts?: RecoveryOptions): Promise<RecoveryResult>;
764
832
 
765
- /**
766
- * `operations.invoke` — the registry-driven call path with the WRITE
767
- * GOVERNOR (ARCHITECTURE section 19.5 R2–R4).
768
- *
769
- * The generated registry lists EVERY implemented operation; this module is
770
- * the deterministic call path for ones that are not a typed convenience of
771
- * their own. The MCP mode tools (`autotask_read` / `autotask_write` /
772
- * `autotask_delete`) dispatch through the same router with the mode pinned;
773
- * `invoke()` itself stays the programmatic escape hatch — its mode is derived
774
- * from the record, so it can never be cross-mode-refused.
775
- * It is deliberately MCP-independent — plain SDK code, no MCP import.
776
- *
777
- * ```ts
778
- * import { invoke } from 'node-autotask/operations';
779
- *
780
- * await invoke(client, 'companies.get', [3]); // read: one request
781
- * await invoke(client, 'companies.update', [3, { companyName: 'A' }]); // write: DRY RUN by default
782
- * await invoke(client, 'companies.update', [3, { companyName: 'A' }], { dryRun: false }); // apply
783
- * await invoke(client, 'companies.delete', [3], { dryRun: false, confirm: 'companies.delete' }); // destructive
784
- * ```
785
- *
786
- * Governor rules (pinned):
787
- * - the operation key must EXACTLY match a registry record (unknown keys
788
- * refuse before any request);
789
- * - a mode-pinned call (the mode tools) REFUSES a cross-mode op before any
790
- * request (the mode is the registry `effect`: read → `read`, write →
791
- * `write`, destructive → `delete`; the refusal message carries the op key
792
- * + the effect + the correct target tool — zero wire, it throws before
793
- * holder/method resolution);
794
- * - a read REFUSES `dryRun: true` (a read has no dry run to run);
795
- * - a write is DRY-RUN-FIRST: unless the caller passes `dryRun: false`, the
796
- * call travels with `dryRun: true` and the real mutating request is never
797
- * issued (the result is the pinned `DryRunResult`, `simulated: true`);
798
- * - a destructive or approval-gated operation (registry `effect` +
799
- * `flags`) REFUSES without its confirmation flag: `confirm` must equal the
800
- * operation key exactly (no booleans, no fuzzy matching) — in BOTH dry-run
801
- * and apply mode (the deliberate act is the call, not the write);
802
- * - query operations (`<resource>.query`) are routed to the resource's
803
- * `queryBounded` (server-side pagination): ONE invoke call returns a
804
- * bounded, complete-enough result — the vendor cursor walk happens inside
805
- * the SDK; the caller passes `limit` as the TOTAL cap (default 500, max
806
- * 2500) and never owns a stream. `queryAll` keeps its raw behavior (the
807
- * unbounded walk; the catalog text steers the caller away for normal work);
808
- * - the governor OPTIONS object is closed: an unknown option key (a typo of
809
- * `dryRun` / `confirm` / `lastModifiedDate`) is refused pre-request (the
810
- * key is named + the valid keys listed — never the values);
811
- * - the query-family params bag (`args[0]` for `query` / `queryAll` /
812
- * `count`) is CLOSED at its top level: the valid key set is per-verb
813
- * (PARAMS_BAG_KEYS — for `query` routed to `queryBounded`:
814
- * filter / limit / latest / includeFields / via / fieldCheck) and an unknown key
815
- * (`filters`, `lmit`, `pageSize`, `cursor`, …) is refused pre-request
816
- * with a typed error naming the key + the valid keys + a did-you-mean
817
- * (`last` → `latest`, issue #59); entity bodies,
818
- * UDF maps and the filter tree stay open (strictness applies to tool
819
- * arguments, not vendor payloads);
820
- * - the caller's `args` are validated against the record's declared
821
- * `inputSchema` BEFORE the method is applied (pre-request, zero wire):
822
- * MORE args than the declared positional list are REFUSED, FEWER than the
823
- * required count are REFUSED, and scalar-typed args (number/string) are
824
- * loosely type-checked — each refusal is a shape-teaching message naming
825
- * the operation, the declared arg list (names + types) and the count
826
- * passed (never the values — redaction discipline). v0.2.0 behavior
827
- * change: extra args were SILENTLY DROPPED (the JS call ignores them);
828
- * v0.3.0 refuses them, so a wrong-arity call can never shadow the
829
- * governed trailing bag or land in the wrong positional slot. The
830
- * governed `{ dryRun, lastModifiedDate? }` bag is NOT a declared arg —
831
- * it travels through the invoke options and is appended by the router.
832
- *
833
- * Dispatch calls the SAME typed method the SDK publishes, with the caller's
834
- * `args` in the method's positional order; for writes the governed
835
- * `{ dryRun, lastModifiedDate? }` bag is appended as the method's final
836
- * `MutationOpts` argument. Every guard that path already has (bounded scans,
837
- * the stale check, the dry-run envelope) is that path's, not a second
838
- * implementation.
839
- */
840
-
841
833
  /** True for an operation that needs a deliberate act before it runs (R4). */
842
834
  declare function needsConfirmation(record: CapabilityRecord): boolean;
843
835
  /**
@@ -845,6 +837,7 @@ declare function needsConfirmation(record: CapabilityRecord): boolean;
845
837
  * verified one-to-one over all registry records.
846
838
  */
847
839
  type InvokeMode = 'read' | 'write' | 'delete';
840
+
848
841
  /**
849
842
  * Validate the caller's positional args against the record's declared
850
843
  * `inputSchema` (A-F2). Refusals are pre-request (zero wire) and shape-
@@ -852,8 +845,7 @@ type InvokeMode = 'read' | 'write' | 'delete';
852
845
  * and the count passed — never the values.
853
846
  *
854
847
  * Rules (the v0.2.0 → v0.3.0 tightening):
855
- * - MORE args than the declared positional list → REFUSED (v0.2.0 silently
856
- * dropped them);
848
+ * - MORE args than the declared positional list → REFUSED;
857
849
  * - FEWER args than the required count → REFUSED (they would have landed in
858
850
  * the wrong positional slot — a bare scalar where an object belongs);
859
851
  * - scalar-typed args (number/string/number[]/object) get a loose typeof
@@ -863,6 +855,7 @@ type InvokeMode = 'read' | 'write' | 'delete';
863
855
  * bare conditions array is refused here, not after the walk has started.
864
856
  */
865
857
  declare function validateDispatchArgs(record: CapabilityRecord, argsIn: readonly unknown[] | null | undefined): void;
858
+
866
859
  /** The CLOSED params-bag key set per query-family verb (`args[0]`).
867
860
  * `query` routes to `queryBounded`, whose method reads only
868
861
  * filter / limit / includeFields / via — `maxRecords` is ignored by it
@@ -907,6 +900,7 @@ declare function validateInvokeOptions(opts: Record<string, unknown> | undefined
907
900
  * MCP client's `list_tools`, which serves the tool's inputSchema.
908
901
  */
909
902
  declare function unknownKeysRefusal(raw: unknown, validKeys: readonly string[], subject: string, operation?: string): AutotaskConfigError | null;
903
+
910
904
  /**
911
905
  * Invoke one registry operation through its typed SDK method — the legacy
912
906
  * path (programmatic escape hatch). The mode is derived from the registry
@@ -934,4 +928,4 @@ declare function invokeWrite(client: AutotaskClient, operation: string, args?: r
934
928
  */
935
929
  declare function invokeDelete(client: AutotaskClient, operation: string, args?: readonly unknown[], opts?: InvokeOptions): Promise<unknown>;
936
930
 
937
- export { AGGREGATE_DATE_BUCKETS, AGGREGATE_DEFAULT_LIMIT, AGGREGATE_DEFAULT_TOP, AGGREGATE_TOP_MAX, type AggregateGroup, type AggregateOptions, type AggregateResult, BLIND_SURFACE_KINDS, type BlindSurfaceKind, type BlindSurfaceOptions, BlindSurfaceRow, CREATE_BLOCKER_KINDS, type CreateGuidanceOptions, type DateBucket, EXPAND_RESOURCE_NAMES_MAX_IDS, type ExpandResourceNameRow, type ExpandResourceNamesOptions, type ExpandResourceNamesResult, FETCH_BY_IDS_CHUNK_SIZE, FETCH_BY_IDS_MAX_ITEMS, FETCH_MANY_MAX_ITEMS, FIELD_CATALOG_HONESTY_NOTE, type FetchByIdsOptions, type FetchManyItem, type FetchManyItemError, type FetchManyItemResult, type FetchManyOptions, type FetchManyResult, FieldCacheKind, type FieldCatalogFieldRow, type FieldCatalogOptions, type FieldCatalogResult, type FieldCatalogRow, type FieldCatalogRowError, INVOKE_OPTION_KEYS, type InvokeMode, type InvokeOptions, MAX_FIELD_CATALOG_WIRE, PARAMS_BAG_KEYS, type ProbeReachabilityOptions, type ProbeReachabilityResult, type ProbeSurfaceRow, RECOVERY_CONFIRM, RECOVERY_DEFAULT_LIMIT, RECOVERY_MAX_LIMIT, type RecoveryDeleteBoundary, type RecoveryInput, type RecoveryMatch, type RecoveryOptions, type RecoveryResult, type ResolveAnyOptions, type ResolveAnyResourceOutcome, type ResolveAnyResult, type SearchAcrossResourcesOptions, type SearchAcrossResourcesResult, type SearchAcrossResourcesRow, WORKFLOW_RESOURCES, aggregate, blindSurfaces, createGuidance, dateBucketLabel, expandResourceNames, fetchByIds, fetchMany, fieldCatalog, invoke, invokeDelete, invokeRead, invokeWrite, needsConfirmation, probeReachability, recovery, relationshipMap, resolveAny, searchAcrossResources, unknownKeysRefusal, validateDispatchArgs, validateFetchManyItems, validateInvokeOptions, validateParamsBag };
931
+ export { AGGREGATE_DATE_BUCKETS, AGGREGATE_DEFAULT_LIMIT, AGGREGATE_DEFAULT_TOP, AGGREGATE_TOP_MAX, type AggregateGroup, type AggregateOptions, type AggregateResult, BLIND_SURFACE_KINDS, type BlindSurfaceKind, type BlindSurfaceOptions, BlindSurfaceRow, CREATE_BLOCKER_KINDS, type CreateGuidanceOptions, type DateBucket, EXPAND_RESOURCE_NAMES_MAX_IDS, type ExpandResourceNameRow, type ExpandResourceNamesOptions, type ExpandResourceNamesResult, FETCH_BY_IDS_CHUNK_SIZE, FETCH_BY_IDS_MAX_ITEMS, FETCH_MANY_MAX_ITEMS, FIELD_CATALOG_HONESTY_NOTE, type FetchByIdsOptions, type FetchManyItem, type FetchManyItemError, type FetchManyItemResult, type FetchManyOptions, type FetchManyResult, FieldCacheKind, type FieldCatalogFieldRow, type FieldCatalogOptions, type FieldCatalogResult, type FieldCatalogRow, type FieldCatalogRowError, INVOKE_OPTION_KEYS, type InvokeMode, type InvokeOptions, MAX_FIELD_CATALOG_WIRE, PARAMS_BAG_KEYS, type ProbeReachabilityOptions, type ProbeReachabilityResult, type ProbeSurfaceRow, RECOVERY_CONFIRM, RECOVERY_DEFAULT_LIMIT, RECOVERY_MAX_LIMIT, type RecoveryDeleteBoundary, type RecoveryInput, type RecoveryMatch, type RecoveryOptions, type RecoveryResult, type ResolveAnyOptions, type ResolveAnyResourceOutcome, type ResolveAnyResult, type SearchAcrossResourcesOptions, type SearchAcrossResourcesResult, type SearchAcrossResourcesRow, UI_LINK_ENTITIES, type UiLinkEntity, type UiLinkInput, type UiLinkResult, WORKFLOW_RESOURCES, aggregate, blindSurfaces, buildUiLink, createGuidance, dateBucketLabel, expandResourceNames, fetchByIds, fetchMany, fieldCatalog, invoke, invokeDelete, invokeRead, invokeWrite, needsConfirmation, probeReachability, recovery, relationshipMap, resolveAny, searchAcrossResources, uiLink, unknownKeysRefusal, validateDispatchArgs, validateFetchManyItems, validateInvokeOptions, validateParamsBag };
@@ -1,7 +1,7 @@
1
- import { a as AutotaskClient, f4 as BlindSurfaceInfo, f5 as RelationshipResource, f6 as BlindSurfaceInventory, f7 as BlindSurfaceRow, f8 as CreateBlockerKind, f9 as CreateGuidanceReport, fa as FieldCacheKind, g as AutotaskConfigError } from '../index-DSnuyiTr.js';
2
- export { fb as FIELD_CACHE_KINDS } from '../index-DSnuyiTr.js';
3
- import { I as Identifier, cE as EmptyReasonInfo, dI as PickListValue, a as FilterCondition } from '../index-BXtKN1M5.js';
4
- export { hp as PICKLIST_VALUE_NOT_SERVED_NOTE } from '../index-BXtKN1M5.js';
1
+ import { a as AutotaskClient, ea as BlindSurfaceInfo, eb as RelationshipResource, ec as BlindSurfaceInventory, ed as BlindSurfaceRow, ee as CreateBlockerKind, ef as CreateGuidanceReport, Z as ZoneName, eg as FieldCacheKind, i as AutotaskConfigError } from '../index-DBoX-Dnk.js';
2
+ export { eh as FIELD_CACHE_KINDS } from '../index-DBoX-Dnk.js';
3
+ import { I as Identifier, cG as EmptyReasonInfo, dI as PickListValue, a as FilterCondition } from '../index-BVtycq-6.js';
4
+ export { hp as PICKLIST_VALUE_NOT_SERVED_NOTE } from '../index-BVtycq-6.js';
5
5
  import { CapabilityRecord } from '../capabilities.js';
6
6
 
7
7
  /**
@@ -20,8 +20,10 @@ declare const WORKFLOW_RESOURCES: readonly string[];
20
20
  interface SearchAcrossResourcesOptions {
21
21
  /** Resource keys to search (default: the five workflow resources). */
22
22
  resources?: readonly string[];
23
- /** Max matches per resource (default 25, max 500). */
23
+ /** Max matches PER RESOURCE (default 25, max 500) — a sweep over N resources can return up to N x limit matches; use `totalLimit` to cap the whole sweep. */
24
24
  limit?: number;
25
+ /** Optional cap on matches ACROSS ALL resources (positive integer). Resources are searched in request order, each asked for `min(limit, remaining)`; once the cap is met the remaining resources are not queried and are listed in `notSearched`. Absent = no cap and the result is unchanged. */
26
+ totalLimit?: number;
25
27
  }
26
28
  /** One searched resource's matches (compact shapes; `Summary = full record`). */
27
29
  interface SearchAcrossResourcesRow {
@@ -35,6 +37,10 @@ interface SearchAcrossResourcesResult {
35
37
  results: SearchAcrossResourcesRow[];
36
38
  /** Requested keys without a `search` helper — skipped and reported, never errored. */
37
39
  skipped: string[];
40
+ /** Only with `totalLimit`: resources that HAVE a `search` helper but were not queried because the cap was already met, in request order. */
41
+ notSearched?: string[];
42
+ /** Only with `totalLimit`: true when more matches may exist — some resource was not searched, or a searched resource returned exactly the quota it was asked for (`min(limit, remaining)`). */
43
+ truncated?: boolean;
38
44
  }
39
45
  /** One fetchMany item: a single-record GET by vendor numeric id. */
40
46
  interface FetchManyItem {
@@ -449,6 +455,68 @@ interface CreateGuidanceOptions {
449
455
  */
450
456
  declare function createGuidance(client: AutotaskClient, opts?: CreateGuidanceOptions): Promise<CreateGuidanceReport>;
451
457
 
458
+ /** entity (plan resource key) -> ExecuteCommand `Code` + id parameter name. */
459
+ declare const ENTITIES: {
460
+ readonly time_entries: {
461
+ readonly code: "EditTimeEntry";
462
+ readonly param: "WorkEntryID";
463
+ };
464
+ readonly tickets: {
465
+ readonly code: "OpenTicketDetail";
466
+ readonly param: "TicketID";
467
+ };
468
+ readonly tasks: {
469
+ readonly code: "OpenTaskDetail";
470
+ readonly param: "TaskID";
471
+ };
472
+ readonly projects: {
473
+ readonly code: "OpenProject";
474
+ readonly param: "ProjectID";
475
+ };
476
+ readonly companies: {
477
+ readonly code: "OpenAccount";
478
+ readonly param: "AccountID";
479
+ };
480
+ readonly contacts: {
481
+ readonly code: "OpenContact";
482
+ readonly param: "ContactID";
483
+ };
484
+ readonly contracts: {
485
+ readonly code: "OpenContract";
486
+ readonly param: "ContractID";
487
+ };
488
+ readonly configuration_items: {
489
+ readonly code: "EditInstalledProduct";
490
+ readonly param: "InstalledProductID";
491
+ };
492
+ };
493
+ type UiLinkEntity = keyof typeof ENTITIES;
494
+ declare const UI_LINK_ENTITIES: UiLinkEntity[];
495
+ /** The input of `buildUiLink` / `operations.uiLink`. */
496
+ interface UiLinkInput {
497
+ /** The plan resource key of the record: one of UI_LINK_ENTITIES. */
498
+ entity: string;
499
+ /** The vendor numeric id (positive safe integer). */
500
+ id?: number;
501
+ /** Tickets only: the displayed ticket number (`T20240101.0001`); exclusive with `id`. */
502
+ ticketNumber?: string;
503
+ /** Explicit UI host (`ww<N>.autotask.net`), overriding derivation. */
504
+ host?: string;
505
+ /** A zone name from the catalog (derives the host the same way as the client base). */
506
+ zone?: ZoneName;
507
+ /** A REST base URL (e.g. the client's) to derive the host from. */
508
+ baseUrl?: string;
509
+ }
510
+ /** Build the deep link, or `undefined` when no UI host can be derived. Throws a typed CONFIG_ERROR on bad input. */
511
+ declare function buildUiLink(input: UiLinkInput): string | undefined;
512
+ /** The `operations.uiLink` result: the URL, or null with the reason no host could be derived. */
513
+ interface UiLinkResult {
514
+ url: string | null;
515
+ reason?: string;
516
+ }
517
+ /** Zero-wire meta op: build the deep link from the client's live REST base (or an explicit `host`). */
518
+ declare function uiLink(client: AutotaskClient, input: UiLinkInput): Promise<UiLinkResult>;
519
+
452
520
  /** The pinned wire cap: `resources × include` above it is refused
453
521
  * pre-request (CONFIG_ERROR naming the computed cost and the cap) —
454
522
  * refused, never truncated. */
@@ -762,82 +830,6 @@ interface RecoveryOptions {
762
830
  */
763
831
  declare function recovery(client: AutotaskClient, input: RecoveryInput, opts?: RecoveryOptions): Promise<RecoveryResult>;
764
832
 
765
- /**
766
- * `operations.invoke` — the registry-driven call path with the WRITE
767
- * GOVERNOR (ARCHITECTURE section 19.5 R2–R4).
768
- *
769
- * The generated registry lists EVERY implemented operation; this module is
770
- * the deterministic call path for ones that are not a typed convenience of
771
- * their own. The MCP mode tools (`autotask_read` / `autotask_write` /
772
- * `autotask_delete`) dispatch through the same router with the mode pinned;
773
- * `invoke()` itself stays the programmatic escape hatch — its mode is derived
774
- * from the record, so it can never be cross-mode-refused.
775
- * It is deliberately MCP-independent — plain SDK code, no MCP import.
776
- *
777
- * ```ts
778
- * import { invoke } from 'node-autotask/operations';
779
- *
780
- * await invoke(client, 'companies.get', [3]); // read: one request
781
- * await invoke(client, 'companies.update', [3, { companyName: 'A' }]); // write: DRY RUN by default
782
- * await invoke(client, 'companies.update', [3, { companyName: 'A' }], { dryRun: false }); // apply
783
- * await invoke(client, 'companies.delete', [3], { dryRun: false, confirm: 'companies.delete' }); // destructive
784
- * ```
785
- *
786
- * Governor rules (pinned):
787
- * - the operation key must EXACTLY match a registry record (unknown keys
788
- * refuse before any request);
789
- * - a mode-pinned call (the mode tools) REFUSES a cross-mode op before any
790
- * request (the mode is the registry `effect`: read → `read`, write →
791
- * `write`, destructive → `delete`; the refusal message carries the op key
792
- * + the effect + the correct target tool — zero wire, it throws before
793
- * holder/method resolution);
794
- * - a read REFUSES `dryRun: true` (a read has no dry run to run);
795
- * - a write is DRY-RUN-FIRST: unless the caller passes `dryRun: false`, the
796
- * call travels with `dryRun: true` and the real mutating request is never
797
- * issued (the result is the pinned `DryRunResult`, `simulated: true`);
798
- * - a destructive or approval-gated operation (registry `effect` +
799
- * `flags`) REFUSES without its confirmation flag: `confirm` must equal the
800
- * operation key exactly (no booleans, no fuzzy matching) — in BOTH dry-run
801
- * and apply mode (the deliberate act is the call, not the write);
802
- * - query operations (`<resource>.query`) are routed to the resource's
803
- * `queryBounded` (server-side pagination): ONE invoke call returns a
804
- * bounded, complete-enough result — the vendor cursor walk happens inside
805
- * the SDK; the caller passes `limit` as the TOTAL cap (default 500, max
806
- * 2500) and never owns a stream. `queryAll` keeps its raw behavior (the
807
- * unbounded walk; the catalog text steers the caller away for normal work);
808
- * - the governor OPTIONS object is closed: an unknown option key (a typo of
809
- * `dryRun` / `confirm` / `lastModifiedDate`) is refused pre-request (the
810
- * key is named + the valid keys listed — never the values);
811
- * - the query-family params bag (`args[0]` for `query` / `queryAll` /
812
- * `count`) is CLOSED at its top level: the valid key set is per-verb
813
- * (PARAMS_BAG_KEYS — for `query` routed to `queryBounded`:
814
- * filter / limit / latest / includeFields / via / fieldCheck) and an unknown key
815
- * (`filters`, `lmit`, `pageSize`, `cursor`, …) is refused pre-request
816
- * with a typed error naming the key + the valid keys + a did-you-mean
817
- * (`last` → `latest`, issue #59); entity bodies,
818
- * UDF maps and the filter tree stay open (strictness applies to tool
819
- * arguments, not vendor payloads);
820
- * - the caller's `args` are validated against the record's declared
821
- * `inputSchema` BEFORE the method is applied (pre-request, zero wire):
822
- * MORE args than the declared positional list are REFUSED, FEWER than the
823
- * required count are REFUSED, and scalar-typed args (number/string) are
824
- * loosely type-checked — each refusal is a shape-teaching message naming
825
- * the operation, the declared arg list (names + types) and the count
826
- * passed (never the values — redaction discipline). v0.2.0 behavior
827
- * change: extra args were SILENTLY DROPPED (the JS call ignores them);
828
- * v0.3.0 refuses them, so a wrong-arity call can never shadow the
829
- * governed trailing bag or land in the wrong positional slot. The
830
- * governed `{ dryRun, lastModifiedDate? }` bag is NOT a declared arg —
831
- * it travels through the invoke options and is appended by the router.
832
- *
833
- * Dispatch calls the SAME typed method the SDK publishes, with the caller's
834
- * `args` in the method's positional order; for writes the governed
835
- * `{ dryRun, lastModifiedDate? }` bag is appended as the method's final
836
- * `MutationOpts` argument. Every guard that path already has (bounded scans,
837
- * the stale check, the dry-run envelope) is that path's, not a second
838
- * implementation.
839
- */
840
-
841
833
  /** True for an operation that needs a deliberate act before it runs (R4). */
842
834
  declare function needsConfirmation(record: CapabilityRecord): boolean;
843
835
  /**
@@ -845,6 +837,7 @@ declare function needsConfirmation(record: CapabilityRecord): boolean;
845
837
  * verified one-to-one over all registry records.
846
838
  */
847
839
  type InvokeMode = 'read' | 'write' | 'delete';
840
+
848
841
  /**
849
842
  * Validate the caller's positional args against the record's declared
850
843
  * `inputSchema` (A-F2). Refusals are pre-request (zero wire) and shape-
@@ -852,8 +845,7 @@ type InvokeMode = 'read' | 'write' | 'delete';
852
845
  * and the count passed — never the values.
853
846
  *
854
847
  * Rules (the v0.2.0 → v0.3.0 tightening):
855
- * - MORE args than the declared positional list → REFUSED (v0.2.0 silently
856
- * dropped them);
848
+ * - MORE args than the declared positional list → REFUSED;
857
849
  * - FEWER args than the required count → REFUSED (they would have landed in
858
850
  * the wrong positional slot — a bare scalar where an object belongs);
859
851
  * - scalar-typed args (number/string/number[]/object) get a loose typeof
@@ -863,6 +855,7 @@ type InvokeMode = 'read' | 'write' | 'delete';
863
855
  * bare conditions array is refused here, not after the walk has started.
864
856
  */
865
857
  declare function validateDispatchArgs(record: CapabilityRecord, argsIn: readonly unknown[] | null | undefined): void;
858
+
866
859
  /** The CLOSED params-bag key set per query-family verb (`args[0]`).
867
860
  * `query` routes to `queryBounded`, whose method reads only
868
861
  * filter / limit / includeFields / via — `maxRecords` is ignored by it
@@ -907,6 +900,7 @@ declare function validateInvokeOptions(opts: Record<string, unknown> | undefined
907
900
  * MCP client's `list_tools`, which serves the tool's inputSchema.
908
901
  */
909
902
  declare function unknownKeysRefusal(raw: unknown, validKeys: readonly string[], subject: string, operation?: string): AutotaskConfigError | null;
903
+
910
904
  /**
911
905
  * Invoke one registry operation through its typed SDK method — the legacy
912
906
  * path (programmatic escape hatch). The mode is derived from the registry
@@ -934,4 +928,4 @@ declare function invokeWrite(client: AutotaskClient, operation: string, args?: r
934
928
  */
935
929
  declare function invokeDelete(client: AutotaskClient, operation: string, args?: readonly unknown[], opts?: InvokeOptions): Promise<unknown>;
936
930
 
937
- export { AGGREGATE_DATE_BUCKETS, AGGREGATE_DEFAULT_LIMIT, AGGREGATE_DEFAULT_TOP, AGGREGATE_TOP_MAX, type AggregateGroup, type AggregateOptions, type AggregateResult, BLIND_SURFACE_KINDS, type BlindSurfaceKind, type BlindSurfaceOptions, BlindSurfaceRow, CREATE_BLOCKER_KINDS, type CreateGuidanceOptions, type DateBucket, EXPAND_RESOURCE_NAMES_MAX_IDS, type ExpandResourceNameRow, type ExpandResourceNamesOptions, type ExpandResourceNamesResult, FETCH_BY_IDS_CHUNK_SIZE, FETCH_BY_IDS_MAX_ITEMS, FETCH_MANY_MAX_ITEMS, FIELD_CATALOG_HONESTY_NOTE, type FetchByIdsOptions, type FetchManyItem, type FetchManyItemError, type FetchManyItemResult, type FetchManyOptions, type FetchManyResult, FieldCacheKind, type FieldCatalogFieldRow, type FieldCatalogOptions, type FieldCatalogResult, type FieldCatalogRow, type FieldCatalogRowError, INVOKE_OPTION_KEYS, type InvokeMode, type InvokeOptions, MAX_FIELD_CATALOG_WIRE, PARAMS_BAG_KEYS, type ProbeReachabilityOptions, type ProbeReachabilityResult, type ProbeSurfaceRow, RECOVERY_CONFIRM, RECOVERY_DEFAULT_LIMIT, RECOVERY_MAX_LIMIT, type RecoveryDeleteBoundary, type RecoveryInput, type RecoveryMatch, type RecoveryOptions, type RecoveryResult, type ResolveAnyOptions, type ResolveAnyResourceOutcome, type ResolveAnyResult, type SearchAcrossResourcesOptions, type SearchAcrossResourcesResult, type SearchAcrossResourcesRow, WORKFLOW_RESOURCES, aggregate, blindSurfaces, createGuidance, dateBucketLabel, expandResourceNames, fetchByIds, fetchMany, fieldCatalog, invoke, invokeDelete, invokeRead, invokeWrite, needsConfirmation, probeReachability, recovery, relationshipMap, resolveAny, searchAcrossResources, unknownKeysRefusal, validateDispatchArgs, validateFetchManyItems, validateInvokeOptions, validateParamsBag };
931
+ export { AGGREGATE_DATE_BUCKETS, AGGREGATE_DEFAULT_LIMIT, AGGREGATE_DEFAULT_TOP, AGGREGATE_TOP_MAX, type AggregateGroup, type AggregateOptions, type AggregateResult, BLIND_SURFACE_KINDS, type BlindSurfaceKind, type BlindSurfaceOptions, BlindSurfaceRow, CREATE_BLOCKER_KINDS, type CreateGuidanceOptions, type DateBucket, EXPAND_RESOURCE_NAMES_MAX_IDS, type ExpandResourceNameRow, type ExpandResourceNamesOptions, type ExpandResourceNamesResult, FETCH_BY_IDS_CHUNK_SIZE, FETCH_BY_IDS_MAX_ITEMS, FETCH_MANY_MAX_ITEMS, FIELD_CATALOG_HONESTY_NOTE, type FetchByIdsOptions, type FetchManyItem, type FetchManyItemError, type FetchManyItemResult, type FetchManyOptions, type FetchManyResult, FieldCacheKind, type FieldCatalogFieldRow, type FieldCatalogOptions, type FieldCatalogResult, type FieldCatalogRow, type FieldCatalogRowError, INVOKE_OPTION_KEYS, type InvokeMode, type InvokeOptions, MAX_FIELD_CATALOG_WIRE, PARAMS_BAG_KEYS, type ProbeReachabilityOptions, type ProbeReachabilityResult, type ProbeSurfaceRow, RECOVERY_CONFIRM, RECOVERY_DEFAULT_LIMIT, RECOVERY_MAX_LIMIT, type RecoveryDeleteBoundary, type RecoveryInput, type RecoveryMatch, type RecoveryOptions, type RecoveryResult, type ResolveAnyOptions, type ResolveAnyResourceOutcome, type ResolveAnyResult, type SearchAcrossResourcesOptions, type SearchAcrossResourcesResult, type SearchAcrossResourcesRow, UI_LINK_ENTITIES, type UiLinkEntity, type UiLinkInput, type UiLinkResult, WORKFLOW_RESOURCES, aggregate, blindSurfaces, buildUiLink, createGuidance, dateBucketLabel, expandResourceNames, fetchByIds, fetchMany, fieldCatalog, invoke, invokeDelete, invokeRead, invokeWrite, needsConfirmation, probeReachability, recovery, relationshipMap, resolveAny, searchAcrossResources, uiLink, unknownKeysRefusal, validateDispatchArgs, validateFetchManyItems, validateInvokeOptions, validateParamsBag };