@taiga-ai/mcp-server 0.36.0-rc.776 → 0.36.0-rc.800

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 +641 -76
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -505,6 +505,7 @@ function hide(inst, key, value) {
505
505
  return own$5(inst, key, value, false);
506
506
  }
507
507
  /** Adds members a table derives from the instance: each builds on first read and shadows as own data, and assignment shadows the same way, as when these were own properties. */
508
+ /* @__NO_SIDE_EFFECTS__ */
508
509
  function derived(computes, table) {
509
510
  for (const key in computes) {
510
511
  const compute = computes[key];
@@ -658,6 +659,7 @@ function newError(Definition) {
658
659
  }
659
660
  return new Definition();
660
661
  }
662
+ /* @__NO_SIDE_EFFECTS__ */
661
663
  function $constructor(name, initializer, proto, params) {
662
664
  const zodProto = {};
663
665
  function Internals(def) {
@@ -788,8 +790,7 @@ const initializer$1 = (inst, def) => {
788
790
  });
789
791
  }
790
792
  };
791
- const $ZodError = $constructor("$ZodError", initializer$1);
792
- $constructor("$ZodError", initializer$1, void 0, { Parent: Error });
793
+ const $ZodError = /* @__PURE__ */ $constructor("$ZodError", initializer$1);
793
794
  /** Get-or-create `obj[key]` as an own data property. A path segment naming an inherited member
794
795
  * ("toString", "constructor") would otherwise read through to the prototype, and assigning
795
796
  * "__proto__" would hit the setter instead of creating a key. */
@@ -1078,7 +1079,7 @@ const guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9
1078
1079
  /** Returns a regex for validating an RFC 9562/4122 UUID.
1079
1080
  *
1080
1081
  * @param version Optionally specify a version 1-8. If no version is specified, all versions are supported. */
1081
- const uuid = (version) => {
1082
+ const uuid$1 = (version) => {
1082
1083
  if (!version) return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
1083
1084
  return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
1084
1085
  };
@@ -1618,8 +1619,8 @@ const $ZodUUID = /*@__PURE__*/ $constructor("$ZodUUID", (inst, def) => {
1618
1619
  v8: 8
1619
1620
  }[def.version];
1620
1621
  if (v === void 0) throw new Error(`Invalid UUID version: "${def.version}"`);
1621
- def.pattern ?? (def.pattern = uuid(v));
1622
- } else def.pattern ?? (def.pattern = uuid());
1622
+ def.pattern ?? (def.pattern = uuid$1(v));
1623
+ } else def.pattern ?? (def.pattern = uuid$1());
1623
1624
  $ZodStringFormat.init(inst, def);
1624
1625
  });
1625
1626
  const $ZodEmail = /*@__PURE__*/ $constructor("$ZodEmail", (inst, def) => {
@@ -5675,6 +5676,14 @@ function object(shape, params) {
5675
5676
  };
5676
5677
  return new ZodObject(def);
5677
5678
  }
5679
+ function strictObject(shape, params) {
5680
+ return new ZodObject({
5681
+ type: "object",
5682
+ shape,
5683
+ catchall: never(),
5684
+ ...normalizeParams(params)
5685
+ });
5686
+ }
5678
5687
  function looseObject(shape, params) {
5679
5688
  return new ZodObject({
5680
5689
  type: "object",
@@ -7941,7 +7950,23 @@ var SdkError = class extends Error {
7941
7950
  stampErrorBrands(this, new.target);
7942
7951
  }
7943
7952
  };
7944
- (class extends SdkError {
7953
+ /**
7954
+ * An {@linkcode SdkError} subclass for HTTP transport failures.
7955
+ *
7956
+ * Thrown by the streamable HTTP transport when the server responds with a
7957
+ * non-OK status code. Narrows {@linkcode SdkError.data | data} to
7958
+ * {@linkcode SdkHttpErrorData} so consumers can inspect the HTTP status
7959
+ * without unsafe casting.
7960
+ *
7961
+ * @example
7962
+ * ```ts source="./sdkErrors.examples.ts#SdkHttpError_basicUsage"
7963
+ * if (error instanceof SdkHttpError) {
7964
+ * console.log(error.status); // number
7965
+ * console.log(error.statusText); // string | undefined
7966
+ * }
7967
+ * ```
7968
+ */
7969
+ var SdkHttpError = class extends SdkError {
7945
7970
  static {
7946
7971
  Object.defineProperty(this, "mcpBrand", { value: "mcp.SdkHttpError" });
7947
7972
  }
@@ -7958,7 +7983,7 @@ var SdkError = class extends Error {
7958
7983
  get statusText() {
7959
7984
  return this.data.statusText;
7960
7985
  }
7961
- });
7986
+ };
7962
7987
  function isPlainObject$7(value) {
7963
7988
  return value !== null && typeof value === "object" && !Array.isArray(value);
7964
7989
  }
@@ -23814,14 +23839,6 @@ var TaigaClient = class {
23814
23839
  async getActivePlan(itemId) {
23815
23840
  return this.request("GET", `/backlog/${seg(itemId)}/plans/active`);
23816
23841
  }
23817
- /** Every plan version of an initiative with the verdict it received, newest first unless `order` says otherwise. */
23818
- async listPlanHistory(itemId, order) {
23819
- return this.request("GET", `/backlog/${seg(itemId)}/plans/history${query$1({ order })}`);
23820
- }
23821
- /** One plan version with its steps, whether or not it is the active one. */
23822
- async getPlan(planId) {
23823
- return this.request("GET", `/plans/${seg(planId)}`);
23824
- }
23825
23842
  async approvePlan(planId) {
23826
23843
  return this.request("POST", `/plans/${seg(planId)}/approve`);
23827
23844
  }
@@ -24097,6 +24114,25 @@ var TaigaClient = class {
24097
24114
  }
24098
24115
  };
24099
24116
  //#endregion
24117
+ //#region ../../packages/types/dist/clouds.js
24118
+ /**
24119
+ * Cloud provider platforms that Taiga can connect to.
24120
+ */
24121
+ const CLOUD_PROVIDERS = [
24122
+ "aws",
24123
+ "gcp",
24124
+ "azure",
24125
+ "upcloud",
24126
+ "kubernetes",
24127
+ "digitalocean",
24128
+ "vercel",
24129
+ "railway",
24130
+ "render",
24131
+ "fly",
24132
+ "on_prem",
24133
+ "other"
24134
+ ];
24135
+ //#endregion
24100
24136
  //#region ../../packages/types/dist/lenient-schema.js
24101
24137
  /**
24102
24138
  * Building blocks for reading JSON that arrives untyped -- a stored jsonb
@@ -24158,6 +24194,14 @@ const optionalUuid = string$2().uuid().optional();
24158
24194
  */
24159
24195
  const optionalLineAnchor = number$1().int().min(0).optional().transform((v) => v ? v : void 0);
24160
24196
  //#endregion
24197
+ //#region ../../packages/types/dist/entitlements.js
24198
+ /**
24199
+ * Which agent implementation serves a planning job or build run (PRO-1331).
24200
+ * Recorded on `agent_jobs.runtime` / `build_runs.runtime` at dispatch so
24201
+ * outcomes can be compared per runtime and the UI can badge runs.
24202
+ */
24203
+ const AGENT_RUNTIMES = ["legacy", "engineer"];
24204
+ //#endregion
24161
24205
  //#region ../../packages/types/dist/tenants.js
24162
24206
  const TENANT_DOCUMENT_TYPES = [
24163
24207
  "policy_security",
@@ -24373,6 +24417,14 @@ Object.fromEntries([...EU_COUNTRIES.map((c) => [c.code, "eu"]), ...EEA_COUNTRIES
24373
24417
  //#endregion
24374
24418
  //#region ../../packages/types/dist/factories.js
24375
24419
  const FACTORY_DOCUMENT_TYPES = ["factory_instructions"];
24420
+ /** The single canonical factory-document type (the free-form Factory Instructions doc). */
24421
+ const FACTORY_INSTRUCTIONS_TYPE = "factory_instructions";
24422
+ /**
24423
+ * The pre-PRO-1671 value of that type. Old clients still name it in URLs
24424
+ * (`/factories/:id/documents/team_instructions`), so the API accepts it as
24425
+ * an alias for a deprecation window.
24426
+ */
24427
+ const LEGACY_FACTORY_INSTRUCTIONS_TYPE = "team_instructions";
24376
24428
  //#endregion
24377
24429
  //#region ../../packages/types/dist/forge.js
24378
24430
  /** Source-control hosts. `bitbucket` is a stored link provider without an adapter yet. */
@@ -24424,6 +24476,15 @@ const FORGE_SUPPORT = {
24424
24476
  ],
24425
24477
  bitbucket: []
24426
24478
  };
24479
+ /**
24480
+ * Whether a repository link under this forge may name a GitHub App
24481
+ * installation's repository: only GitHub's. Stored under another forge, the
24482
+ * link would be dispatched with GitHub credentials while the rest of its
24483
+ * lifecycle reads it as that forge.
24484
+ */
24485
+ function linksGitHubAppRepositories(provider) {
24486
+ return provider === "github";
24487
+ }
24427
24488
  const FORGE_TERMS = {
24428
24489
  github: {
24429
24490
  name: "GitHub",
@@ -24479,6 +24540,11 @@ const PRODUCT_DOCUMENT_TYPES = [
24479
24540
  "product_instructions"
24480
24541
  ];
24481
24542
  /**
24543
+ * The pre-PRO-1671 value of `product_instructions`. Old clients still name it
24544
+ * in URLs, so the API accepts it as an alias for a deprecation window.
24545
+ */
24546
+ const LEGACY_PRODUCT_INSTRUCTIONS_TYPE = "project_instructions";
24547
+ /**
24482
24548
  * The document types the codebase-intelligence agent can derive from a repo --
24483
24549
  * the valid values for a single-document reality refresh (PRO-1141).
24484
24550
  *
@@ -24574,6 +24640,8 @@ const PRODUCT_DOCUMENT_DISPLAY_NAMES = {
24574
24640
  service_blueprint: "Service Blueprint"
24575
24641
  };
24576
24642
  const PRODUCT_DOCUMENT_ORIGINS = ["plan", "reality"];
24643
+ /** The forges a repository link can name: `FORGE_PROVIDERS`, under the name links have always used. */
24644
+ const VCS_PROVIDERS = FORGE_PROVIDERS;
24577
24645
  //#endregion
24578
24646
  //#region ../../packages/types/dist/route-key.js
24579
24647
  /**
@@ -25532,6 +25600,29 @@ object({
25532
25600
  [...BUILD_RUN_ACTIVE_STATUSES.filter((s) => s !== "reviewing")];
25533
25601
  //#endregion
25534
25602
  //#region ../../packages/types/dist/agents.js
25603
+ const AGENT_JOB_TYPES = [
25604
+ "generate_document",
25605
+ "generate_backlog",
25606
+ "plan_backlog_item",
25607
+ "infer_backlog_dependencies",
25608
+ "deploy",
25609
+ "provision_infrastructure",
25610
+ "health_check",
25611
+ "refresh_reality_docs",
25612
+ "derive_policy_update",
25613
+ "derive_design_from_documents",
25614
+ "sync_design_tokens",
25615
+ "generate_design_component",
25616
+ "maintenance_sweep",
25617
+ "maintenance_verify",
25618
+ "propose_ui_concepts",
25619
+ "iterate_ui_concept",
25620
+ "fill_questionnaire",
25621
+ "read_questionnaire_layout",
25622
+ "generate_ui_direction",
25623
+ "assess_policy_conformance",
25624
+ "replan_run"
25625
+ ];
25535
25626
  /**
25536
25627
  * Why a PROMPTED `generate_backlog` job planned nothing.
25537
25628
  *
@@ -25944,6 +26035,23 @@ const MCP_TOOLSETS = [
25944
26035
  /** Longest request for changes from Taiga (PRO-3035): about four pages of prose. */
25945
26036
  const CHANGE_REQUEST_MAX_CHARS = 1e4;
25946
26037
  //#endregion
26038
+ //#region ../../packages/types/dist/requests.js
26039
+ /** Every way a request can be answered, whatever its kind. */
26040
+ const REQUEST_EXITS = [
26041
+ "resume_run",
26042
+ "replan",
26043
+ "clear",
26044
+ "leave_line",
26045
+ "approve",
26046
+ "reject",
26047
+ "merge",
26048
+ "close",
26049
+ "request_changes",
26050
+ "done",
26051
+ "dismiss",
26052
+ "reviewed"
26053
+ ];
26054
+ //#endregion
25947
26055
  //#region ../../packages/types/dist/maintenance.js
25948
26056
  /**
25949
26057
  * Maintenance taxonomy + API DTOs.
@@ -26269,6 +26377,19 @@ object({
26269
26377
  */
26270
26378
  const MAINTENANCE_LICENSE_FILTER_MAX = 4096;
26271
26379
  //#endregion
26380
+ //#region ../../packages/types/dist/custom-documents.js
26381
+ /**
26382
+ * Shared types for the custom-documents feature: customer-uploaded reference
26383
+ * files (PDFs, Markdown, OpenAPI specs, etc.) indexed into a Bedrock
26384
+ * Knowledge Base for retrieval by Taiga's internal agents.
26385
+ */
26386
+ const CUSTOM_DOCUMENT_STATUSES = [
26387
+ "pending",
26388
+ "ingesting",
26389
+ "ready",
26390
+ "failed"
26391
+ ];
26392
+ //#endregion
26272
26393
  //#region ../../packages/types/dist/design-tokens.js
26273
26394
  /**
26274
26395
  * The brand grounding contract (PRO-929).
@@ -26444,6 +26565,457 @@ object({
26444
26565
  fontSize: lenient(union([string$2(), number$1()]))
26445
26566
  });
26446
26567
  //#endregion
26568
+ //#region ../../packages/types/dist/questionnaires.js
26569
+ /**
26570
+ * Questionnaire filling (PRO-932).
26571
+ *
26572
+ * A customer uploads their own requirement spreadsheet; Taiga answers what the
26573
+ * project's evidence settles, cites the document version each answer rests on,
26574
+ * and hands back the gaps. The register these types describe is the durable
26575
+ * object -- the workbook is an import format on one side and an export format
26576
+ * on the other.
26577
+ */
26578
+ /**
26579
+ * Lifecycle of one questionnaire.
26580
+ *
26581
+ * `filling` is deliberately NOT set by the fill workflow (PRO-1187), and that
26582
+ * is a decision rather than an omission. A status set at the start of a
26583
+ * multi-minute run needs something to clear it when the run does not finish --
26584
+ * and if the worker dies mid-fill, nothing would: `agent_jobs` has a reaper for
26585
+ * stale JOBS, but it knows nothing about this table, so the register would read
26586
+ * `filling` forever. A state nothing can leave is worse than one nothing
26587
+ * enters.
26588
+ *
26589
+ * "Is a fill running" is already answerable, and from the row that has a reaper:
26590
+ * an active `fill_questionnaire` job with this questionnaire as its target.
26591
+ * Wire `filling` up when it comes with a path off it.
26592
+ */
26593
+ /**
26594
+ * `reading` and `needs_columns` are the import itself (PRO-1506). A workbook
26595
+ * is stored and its row exists from the first byte; the column read runs as
26596
+ * a job. `reading` is that job in flight; `needs_columns` is the read done
26597
+ * without confidence, waiting for a person to confirm the map. Only once the
26598
+ * map is confirmed do items exist and the row becomes `draft`.
26599
+ */
26600
+ /**
26601
+ * A sheet map's bounds, Excel's own: a column index becomes a column letter
26602
+ * in a cell reference the export writes to, so an unbounded one names
26603
+ * whatever it likes.
26604
+ */
26605
+ const EXCEL_MAX_COLUMN = 16384;
26606
+ const EXCEL_MAX_ROW = 1048576;
26607
+ //#endregion
26608
+ //#region ../../packages/types/dist/product-network.js
26609
+ /**
26610
+ * Where an engineer build's sandbox may connect to (PRO-2793, part of
26611
+ * PRO-1980).
26612
+ *
26613
+ * The engineer pod's credential gateway is the sandbox's only way out. By
26614
+ * default it lets through a standard list: the public package registries,
26615
+ * toolchain downloads, container registries, GitHub for reading public
26616
+ * dependencies, and the tenant's own registries. A product adds to that:
26617
+ *
26618
+ * - `allowlist` (the default, also what `null` means): the standard list plus
26619
+ * the product's own `networkHosts`.
26620
+ * - `unrestricted`: any public host. For a product whose builds need hosts
26621
+ * nobody can list in advance; the gateway still refuses private and
26622
+ * metadata addresses, and still never hands the sandbox a credential.
26623
+ *
26624
+ * A host is one exact name (`api.example.com`). There are no wildcards: a
26625
+ * wildcard over a multi-label public suffix (`*.co.uk`) or a provider's
26626
+ * namespace would admit every tenant under it, and telling those apart needs
26627
+ * the public suffix list. A build that needs many names under one domain is
26628
+ * what `unrestricted` is for.
26629
+ */
26630
+ const PRODUCT_NETWORK_ACCESS = ["allowlist", "unrestricted"];
26631
+ /**
26632
+ * A host a product may add: lowercase DNS labels, at least two, ending in a
26633
+ * letter label. No wildcard, scheme, port, path or IP literal.
26634
+ */
26635
+ const PRODUCT_NETWORK_HOST_PATTERN = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z0-9-]{0,61}[a-z0-9]$/;
26636
+ /**
26637
+ * Domains where anyone can host content under their own name: a bucket, an
26638
+ * app, a tunnel. Listing one whole would let a prompt injection send code to
26639
+ * a bucket the attacker made, the way the gateway's standard list never lists
26640
+ * a shared CDN whole. A specific name under one (`my-bucket.s3.amazonaws.com`)
26641
+ * is fine.
26642
+ */
26643
+ const SHARED_HOSTING_DOMAINS = [
26644
+ "amazonaws.com",
26645
+ "s3.amazonaws.com",
26646
+ "cloudfront.net",
26647
+ "googleapis.com",
26648
+ "storage.googleapis.com",
26649
+ "appspot.com",
26650
+ "firebaseapp.com",
26651
+ "web.app",
26652
+ "blob.core.windows.net",
26653
+ "azureedge.net",
26654
+ "azurewebsites.net",
26655
+ "githubusercontent.com",
26656
+ "github.io",
26657
+ "herokuapp.com",
26658
+ "vercel.app",
26659
+ "netlify.app",
26660
+ "pages.dev",
26661
+ "workers.dev",
26662
+ "trycloudflare.com",
26663
+ "ngrok.io",
26664
+ "ngrok-free.app",
26665
+ "onrender.com",
26666
+ "fly.dev"
26667
+ ];
26668
+ /** Whether `host` has the shape of a host a product may list. */
26669
+ function isProductNetworkHost(host) {
26670
+ return PRODUCT_NETWORK_HOST_PATTERN.test(host);
26671
+ }
26672
+ /** Whether `host` is a domain anyone can host content on, listed whole. */
26673
+ function isSharedHostingDomain(host) {
26674
+ return SHARED_HOSTING_DOMAINS.includes(host);
26675
+ }
26676
+ strictObject({});
26677
+ const uuid = string$2().uuid();
26678
+ const sha256 = string$2().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex characters");
26679
+ object({ jobId: string$2() });
26680
+ /** An upload's grant: a presigned PUT to staging and the headers it signed. */
26681
+ const uploadGrant = object({
26682
+ id: string$2(),
26683
+ url: string$2(),
26684
+ headers: record(string$2(), string$2()),
26685
+ expiresAt: string$2()
26686
+ });
26687
+ object({ version: number$1().int().min(1) });
26688
+ /** The uploads a product's move could not re-file, named while they fit the answer (PRO-3497). */
26689
+ const failedDocuments = array(object({
26690
+ id: string$2(),
26691
+ fileName: string$2(),
26692
+ error: string$2()
26693
+ }));
26694
+ object({
26695
+ backlogItemId: string$2(),
26696
+ divergenceCount: number$1(),
26697
+ created: boolean()
26698
+ });
26699
+ /** The options of a policy fix: build it once planned, and refuse it when the violation was fixed since. */
26700
+ const policyFixOptions = {
26701
+ autoBuild: boolean().optional(),
26702
+ refuseIfFixedSinceAssessment: boolean().optional()
26703
+ };
26704
+ object({
26705
+ findings: number$1(),
26706
+ findingIds: array(string$2()).nullable()
26707
+ });
26708
+ /** An ignore's expiry, when it has one, is in the future. */
26709
+ const expiresInFuture = (expiresAt) => !expiresAt || new Date(expiresAt).getTime() > Date.now();
26710
+ const EXPIRY_IN_FUTURE = {
26711
+ message: "The ignore expiry must be in the future.",
26712
+ path: ["ignoreExpiresAt"]
26713
+ };
26714
+ const ignoreNote = string$2().trim().max(280).nullish();
26715
+ const ignoreExpiresAt = string$2().datetime({ offset: true }).nullish();
26716
+ const productDocumentType = _enum([...PRODUCT_DOCUMENT_TYPES, LEGACY_PRODUCT_INSTRUCTIONS_TYPE]).transform((type) => type === "project_instructions" ? "product_instructions" : type);
26717
+ const customDocumentStatus = _enum(CUSTOM_DOCUMENT_STATUSES);
26718
+ const cloudPreferences = object({
26719
+ iacTool: _enum([
26720
+ "terraform",
26721
+ "pulumi",
26722
+ "cdk",
26723
+ "none"
26724
+ ]).nullable().optional(),
26725
+ stateBackend: _enum([
26726
+ "aws-s3",
26727
+ "gcs",
26728
+ "azurerm",
26729
+ "tfcloud",
26730
+ "other"
26731
+ ]).nullable().optional(),
26732
+ ciSystem: _enum([
26733
+ "github-actions",
26734
+ "gitlab-ci",
26735
+ "circleci",
26736
+ "jenkins",
26737
+ "other"
26738
+ ]).nullable().optional(),
26739
+ authMethod: _enum([
26740
+ "oidc",
26741
+ "static-keys",
26742
+ "unknown"
26743
+ ]).optional(),
26744
+ accountIsolation: _enum([
26745
+ "per-env",
26746
+ "shared",
26747
+ "unknown"
26748
+ ]).optional()
26749
+ }).optional();
26750
+ const cloudBestPractices = object({
26751
+ dedicatedAccount: boolean().optional(),
26752
+ oidcAuth: boolean().optional(),
26753
+ regionMatchesPolicy: boolean().optional(),
26754
+ stateInSameAccount: boolean().optional()
26755
+ }).optional();
26756
+ const cloudProviderConfig = discriminatedUnion("provider", [
26757
+ object({
26758
+ provider: literal("aws"),
26759
+ accountId: string$2().regex(/^\d{12}$/, "AWS account ID must be 12 digits").optional(),
26760
+ region: string$2().min(1),
26761
+ preferences: cloudPreferences,
26762
+ bestPractices: cloudBestPractices
26763
+ }),
26764
+ object({
26765
+ provider: literal("gcp"),
26766
+ projectId: string$2().regex(/^[a-z][a-z0-9-]{4,28}[a-z0-9]$/, "Invalid GCP project ID").optional(),
26767
+ region: string$2().min(1),
26768
+ preferences: cloudPreferences,
26769
+ bestPractices: cloudBestPractices
26770
+ }),
26771
+ object({
26772
+ provider: literal("azure"),
26773
+ subscriptionId: string$2().uuid("Azure subscription ID must be a UUID").optional(),
26774
+ tenantId: string$2().uuid("Azure tenant ID must be a UUID").optional(),
26775
+ region: string$2().min(1),
26776
+ preferences: cloudPreferences,
26777
+ bestPractices: cloudBestPractices
26778
+ }),
26779
+ object({
26780
+ provider: literal("upcloud"),
26781
+ zone: string$2().min(1),
26782
+ username: string$2().min(1).optional(),
26783
+ authMethod: _enum(["password", "token"]).optional(),
26784
+ preferences: cloudPreferences,
26785
+ bestPractices: cloudBestPractices
26786
+ })
26787
+ ]);
26788
+ const columnIndex = number$1().int().min(1).max(EXCEL_MAX_COLUMN);
26789
+ const sheetMap = object({
26790
+ sheetName: string$2().min(1).max(120),
26791
+ idColumn: columnIndex,
26792
+ questionColumn: columnIndex,
26793
+ detailColumns: array(columnIndex).max(20).optional(),
26794
+ sectionColumn: columnIndex.optional(),
26795
+ answerColumn: columnIndex,
26796
+ justificationColumn: columnIndex.optional(),
26797
+ firstDataRow: number$1().int().min(1).max(EXCEL_MAX_ROW)
26798
+ });
26799
+ const answerValue = string$2().trim().min(1).max(64);
26800
+ const justification = string$2().trim().max(2e3);
26801
+ const notApplicableReason = string$2().trim().min(1).max(1200);
26802
+ strictObject({ comment: string$2().trim().min(1).max(PLAN_REJECTION_COMMENT_MAX_CHARS) });
26803
+ strictObject({ expectedRunId: uuid.optional() }), strictObject({ force: boolean().optional() });
26804
+ strictObject({
26805
+ notes: string$2().trim().min(1).max(CHANGE_REQUEST_MAX_CHARS),
26806
+ /** Show the revised plan before the run continues (PRO-3164). */
26807
+ reviewPlan: boolean().optional(),
26808
+ /** The repository whose pull request should change, by its full name, for a run in several (PRO-3346). */
26809
+ repository: string$2().trim().min(1).max(255).optional()
26810
+ }), object({ steer: _enum([
26811
+ "replanning",
26812
+ "after_step",
26813
+ "after_round",
26814
+ "held"
26815
+ ]).optional() });
26816
+ strictObject({
26817
+ exit: _enum(REQUEST_EXITS),
26818
+ comment: string$2().trim().min(1).max(PLAN_REJECTION_COMMENT_MAX_CHARS).optional(),
26819
+ force: boolean().optional()
26820
+ }).refine((answer) => answer.exit === "reject" === (answer.comment !== void 0), {
26821
+ message: "A rejection takes a comment for the planner, and no other answer takes one.",
26822
+ path: ["comment"]
26823
+ }).refine((answer) => answer.exit === "replan" || answer.force === void 0, {
26824
+ message: "Only Plan again can plan anyway.",
26825
+ path: ["force"]
26826
+ });
26827
+ strictObject({ type: productDocumentType }), object({
26828
+ version: number$1().int().min(1),
26829
+ unknownCitations: object({
26830
+ shown: array(string$2()),
26831
+ count: number$1().int().min(0)
26832
+ })
26833
+ }), strictObject({ type: productDocumentType }), strictObject({ type: productDocumentType }), object({ documentId: string$2().uuid() }), strictObject({
26834
+ githubRepositoryId: uuid.optional(),
26835
+ /** A GitLab project, by the connection whose bot reaches it and GitLab's numeric id (P-PRO-150). */
26836
+ gitlabConnectionId: uuid.optional(),
26837
+ gitlabProjectId: number$1().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
26838
+ provider: _enum(VCS_PROVIDERS).optional().default("github"),
26839
+ repositoryName: string$2().min(1).max(512).optional(),
26840
+ repositoryUrl: string$2().url().max(2048).optional(),
26841
+ repositoryDefaultBranch: string$2().max(255).optional().default("main"),
26842
+ /** The link this one replaces, retired in the same transaction (PRO-2522). */
26843
+ replacesRepositoryId: uuid.optional()
26844
+ }).refine((b) => b.gitlabConnectionId === void 0 === (b.gitlabProjectId === void 0), { message: "gitlabConnectionId and gitlabProjectId go together" }).refine((b) => b.gitlabConnectionId === void 0 || b.githubRepositoryId === void 0, { message: "A link is to a GitHub repository or a GitLab project, not both" }).refine((b) => b.githubRepositoryId === void 0 || linksGitHubAppRepositories(b.provider), { message: "githubRepositoryId is a GitHub repository; provider must be github" }), strictObject({
26845
+ repositoryId: uuid,
26846
+ baseBranch: string$2().trim().min(1).max(255).nullable()
26847
+ }), object({
26848
+ effectiveBranch: string$2(),
26849
+ protection: object({
26850
+ protected: boolean(),
26851
+ requiredStatusChecks: array(string$2()),
26852
+ enforcementLevel: string$2().nullable()
26853
+ }).nullable()
26854
+ }), strictObject({
26855
+ license: string$2().trim().min(1).max(200),
26856
+ ignoreReason: _enum(MAINTENANCE_IGNORE_REASONS),
26857
+ ignoreNote,
26858
+ ignoreExpiresAt
26859
+ }).refine((args) => expiresInFuture(args.ignoreExpiresAt), EXPIRY_IN_FUTURE), strictObject({
26860
+ license: string$2().trim().min(1).max(200),
26861
+ findingIds: array(uuid).min(1).optional()
26862
+ }), strictObject({ host: string$2().trim().toLowerCase().refine(isProductNetworkHost, { message: "A host is one exact DNS name, such as api.example.com: no wildcard, scheme, port or path" }).refine((host) => !isSharedHostingDomain(host), { message: "Anyone can host content on this domain, so it cannot be listed whole; list the one host you need under it" }) }), strictObject({
26863
+ type: _enum(AGENT_JOB_TYPES),
26864
+ documentType: string$2().max(30).optional(),
26865
+ priority: number$1().int().min(0).max(99).optional(),
26866
+ metadata: record(string$2(), unknown$1()).optional(),
26867
+ /** Which implementation should serve it (PRO-1332): a request the server may refuse. */
26868
+ runtime: _enum(AGENT_RUNTIMES).optional()
26869
+ }), strictObject({
26870
+ fileName: string$2().trim().min(1).max(1024),
26871
+ sizeBytes: number$1().int().nonnegative(),
26872
+ sha256
26873
+ }), object({ upload: uploadGrant }), strictObject({ uploadId: uuid }), object({
26874
+ questionnaireId: string$2(),
26875
+ jobId: string$2()
26876
+ }), strictObject({ mode: _enum(["generate", "republish"]).default("generate") }), strictObject({ docTypes: array(_enum(REALITY_DERIVED_DOCUMENT_TYPES)).min(1).max(REALITY_DERIVED_DOCUMENT_TYPES.length).optional() }), object({ jobIds: array(string$2()) }), object({ cancelledJobIds: array(string$2()) }), strictObject({
26877
+ factoryId: uuid,
26878
+ stopLine: boolean().optional()
26879
+ }), object({
26880
+ changed: boolean(),
26881
+ previousFactoryId: string$2().nullable(),
26882
+ lineStopped: boolean(),
26883
+ failedDocuments,
26884
+ /** How many uploads kept the old factory; null while not known, never read as none. */
26885
+ failedCount: number$1().int().min(0).nullable()
26886
+ }), strictObject({ documentIds: array(uuid).min(1).max(100).optional() }), object({
26887
+ rescopedCount: number$1().int().min(0).nullable(),
26888
+ failedDocuments,
26889
+ failedCount: number$1().int().min(0).nullable()
26890
+ }), strictObject({ repositoryId: uuid }), strictObject({
26891
+ ecosystem: string$2().min(1).max(50),
26892
+ packageName: string$2().min(1).max(255),
26893
+ /** The installed version, for a package resolved at several in a monorepo. */
26894
+ currentVersion: string$2().min(1).max(100).nullish(),
26895
+ /** The linked repository the group belongs to: a fix touches one. */
26896
+ productRepositoryId: uuid.nullish(),
26897
+ /** Build the fix as soon as it is planned (PRO-949). */
26898
+ autoBuild: boolean().optional()
26899
+ }), object({
26900
+ backlogItemId: string$2(),
26901
+ findingCount: number$1()
26902
+ }), strictObject({
26903
+ ...policyFixOptions,
26904
+ controlId: string$2().min(1).max(40)
26905
+ }), strictObject({ environments: array(string$2()).default(["development"]) }), strictObject({
26906
+ connection: object({
26907
+ name: string$2().min(1).max(150),
26908
+ provider: _enum(CLOUD_PROVIDERS),
26909
+ providerConfig: cloudProviderConfig
26910
+ }).refine((connection) => connection.provider === connection.providerConfig.provider, {
26911
+ message: "connection.provider must match connection.providerConfig.provider",
26912
+ path: ["providerConfig", "provider"]
26913
+ }),
26914
+ environment: object({
26915
+ name: string$2().min(1).max(100),
26916
+ slug: string$2().min(1).max(63).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Slug must be lowercase letters, digits, and dashes"),
26917
+ type: _enum(ENVIRONMENT_TYPES),
26918
+ ordinal: number$1().int().min(0).default(0),
26919
+ isProtected: boolean().default(false)
26920
+ }).optional()
26921
+ });
26922
+ object({
26923
+ status: customDocumentStatus.nullable(),
26924
+ /** The retry itself threw; absent when it went through. */
26925
+ error: string$2().optional()
26926
+ });
26927
+ strictObject({ type: _enum([...FACTORY_DOCUMENT_TYPES, LEGACY_FACTORY_INSTRUCTIONS_TYPE]).transform((type) => type === "team_instructions" ? FACTORY_INSTRUCTIONS_TYPE : type) });
26928
+ strictObject({ type: _enum(TENANT_DOCUMENT_TYPES) }), strictObject({
26929
+ name: string$2().min(1).max(50),
26930
+ action: _enum(["accept", "decline"])
26931
+ }), object({
26932
+ applied: _enum([
26933
+ "draft",
26934
+ "published",
26935
+ "declined"
26936
+ ]),
26937
+ version: number$1().int().nullable()
26938
+ }), strictObject({
26939
+ fileName: string$2().trim().min(1).max(255),
26940
+ mime: string$2().min(1).max(255),
26941
+ sizeBytes: number$1().int().positive(),
26942
+ sha256,
26943
+ factoryId: string$2().optional(),
26944
+ productId: string$2().optional(),
26945
+ origin: string$2().optional()
26946
+ }), discriminatedUnion("deduplicated", [object({
26947
+ deduplicated: literal(true),
26948
+ documentId: string$2(),
26949
+ factoryId: string$2().nullable(),
26950
+ status: customDocumentStatus
26951
+ }), object({
26952
+ deduplicated: literal(false),
26953
+ upload: uploadGrant
26954
+ })]), strictObject({ uploadId: uuid }), object({
26955
+ documentId: string$2(),
26956
+ factoryId: string$2().nullable(),
26957
+ deduplicated: boolean(),
26958
+ status: customDocumentStatus.nullable(),
26959
+ /** Filing it threw; absent when it went through. */
26960
+ error: string$2().optional()
26961
+ }), strictObject({ ids: array(uuid).min(1).max(100) }), object({
26962
+ failedIds: array(string$2()).nullable(),
26963
+ deletedIds: array(string$2()).optional()
26964
+ }), strictObject({ ids: array(uuid).min(1).max(25) }), object({ referenced: array(string$2()) }), strictObject({
26965
+ approve: array(string$2().min(1).max(100)).max(200).default([]),
26966
+ remove: array(string$2().min(1).max(100)).max(200).default([])
26967
+ }).refine((b) => b.approve.length + b.remove.length > 0, { message: "Name a license to approve or remove" }), object({ version: number$1().nullable() });
26968
+ strictObject({
26969
+ ignoreReason: _enum(MAINTENANCE_IGNORE_REASONS),
26970
+ ignoreNote,
26971
+ ignoreExpiresAt
26972
+ }).refine((args) => expiresInFuture(args.ignoreExpiresAt), EXPIRY_IN_FUTURE), strictObject({ autoBuild: boolean().optional() }), object({ backlogItemId: string$2() });
26973
+ strictObject(policyFixOptions);
26974
+ strictObject({ tier: _enum([
26975
+ "development",
26976
+ "staging",
26977
+ "production"
26978
+ ]) });
26979
+ object({
26980
+ url: string$2().url(),
26981
+ expiresAt: string$2(),
26982
+ written: number$1(),
26983
+ unwrittenCount: number$1(),
26984
+ summary: object({
26985
+ byTaiga: number$1(),
26986
+ byYou: number$1(),
26987
+ notApplicable: number$1(),
26988
+ blank: number$1()
26989
+ })
26990
+ }), strictObject({
26991
+ columnMap: object({ sheets: array(sheetMap).min(1).max(50) }),
26992
+ answerVocabulary: array(string$2().min(1).max(64)).max(16).nullable().optional(),
26993
+ answerLegend: string$2().max(4e3).nullable().optional()
26994
+ }), object({
26995
+ imported: number$1(),
26996
+ skippedRows: number$1()
26997
+ });
26998
+ discriminatedUnion("action", [
26999
+ strictObject({ action: literal("accept") }),
27000
+ strictObject({ action: literal("reject") }),
27001
+ strictObject({
27002
+ action: literal("edit"),
27003
+ answerValue: answerValue.optional(),
27004
+ justification: justification.optional()
27005
+ }),
27006
+ strictObject({
27007
+ action: literal("answer"),
27008
+ answerValue,
27009
+ justification: justification.optional()
27010
+ }),
27011
+ strictObject({
27012
+ action: literal("not_applicable"),
27013
+ /** The token the form uses for it, when it has one -- `NA`, `N/A`, `es`. */
27014
+ answerValue: answerValue.optional(),
27015
+ reason: notApplicableReason
27016
+ })
27017
+ ]);
27018
+ //#endregion
26447
27019
  //#region ../../packages/types/dist/auto-build.js
26448
27020
  /**
26449
27021
  * Auto-build: the review-plans gate (PRO-1305).
@@ -26528,30 +27100,6 @@ Object.freeze({
26528
27100
  applicationOwnership: true
26529
27101
  });
26530
27102
  //#endregion
26531
- //#region ../../packages/types/dist/product-network.js
26532
- /**
26533
- * Where an engineer build's sandbox may connect to (PRO-2793, part of
26534
- * PRO-1980).
26535
- *
26536
- * The engineer pod's credential gateway is the sandbox's only way out. By
26537
- * default it lets through a standard list: the public package registries,
26538
- * toolchain downloads, container registries, GitHub for reading public
26539
- * dependencies, and the tenant's own registries. A product adds to that:
26540
- *
26541
- * - `allowlist` (the default, also what `null` means): the standard list plus
26542
- * the product's own `networkHosts`.
26543
- * - `unrestricted`: any public host. For a product whose builds need hosts
26544
- * nobody can list in advance; the gateway still refuses private and
26545
- * metadata addresses, and still never hands the sandbox a credential.
26546
- *
26547
- * A host is one exact name (`api.example.com`). There are no wildcards: a
26548
- * wildcard over a multi-label public suffix (`*.co.uk`) or a provider's
26549
- * namespace would admit every tenant under it, and telling those apart needs
26550
- * the public suffix list. A build that needs many names under one domain is
26551
- * what `unrestricted` is for.
26552
- */
26553
- const PRODUCT_NETWORK_ACCESS = ["allowlist", "unrestricted"];
26554
- //#endregion
26555
27103
  //#region src/compat.ts
26556
27104
  /**
26557
27105
  * Why this server should not serve the API it reached, or null when it may
@@ -26596,7 +27144,6 @@ const TOOLSET_OF = {
26596
27144
  taiga_list_initiatives: "core",
26597
27145
  taiga_get_initiative: "core",
26598
27146
  taiga_get_plan: "core",
26599
- taiga_list_plans: "core",
26600
27147
  taiga_list_runs: "core",
26601
27148
  taiga_get_run: "core",
26602
27149
  taiga_get_line: "core",
@@ -26673,6 +27220,39 @@ const TOOLSET_OF = {
26673
27220
  taiga_retry_knowledge: "documents"
26674
27221
  };
26675
27222
  /**
27223
+ * Deliver & Operate's tools (PRO-3834): initiatives, plans, runs and the line, fixes, environments, deployments,
27224
+ * monitoring and delivery metrics. An organization whose plan refuses delivery work does not see them, as its web app
27225
+ * shows none of their views; the API says which (`deliveryIncluded` at introspection), so the plan, not the key,
27226
+ * decides. Fixing a finding plans and builds, so it goes with them.
27227
+ */
27228
+ const DELIVERY_TOOLS = /* @__PURE__ */ new Set([
27229
+ "taiga_list_initiatives",
27230
+ "taiga_get_initiative",
27231
+ "taiga_get_plan",
27232
+ "taiga_list_runs",
27233
+ "taiga_get_run",
27234
+ "taiga_get_line",
27235
+ "taiga_queue_initiative",
27236
+ "taiga_move_initiative",
27237
+ "taiga_review_plan",
27238
+ "taiga_plan_again",
27239
+ "taiga_resume_initiative",
27240
+ "taiga_stop_run",
27241
+ "taiga_request_changes",
27242
+ "taiga_request_initiatives",
27243
+ "taiga_fix_finding",
27244
+ "taiga_fix_policy_violation",
27245
+ "taiga_set_auto_build",
27246
+ "taiga_set_auto_merge",
27247
+ "taiga_pause_line",
27248
+ "taiga_create_environment",
27249
+ "taiga_update_environment",
27250
+ "taiga_get_deployments",
27251
+ "taiga_get_monitoring",
27252
+ "taiga_get_delivery_metrics",
27253
+ "taiga_sync_design_tokens"
27254
+ ]);
27255
+ /**
26676
27256
  * TAIGA_TOOLSETS as written: comma-separated names, or "all"; a name it does not know is said, not ignored, and so
26677
27257
  * is a value that names none.
26678
27258
  */
@@ -26903,7 +27483,7 @@ function setupNextStep(product) {
26903
27483
  if (isImportedProduct(product)) switch (importStatusOf(product)) {
26904
27484
  case "analyzing":
26905
27485
  case "generating_docs": return `The import is running and derives the documents from the code (taiga_wait (jobId) follows its job). Then review them, and ${FINISH_DISCOVERY}`;
26906
- case "complete": return "The import is done: review the reality documents (taiga_get_product_document without type), then taiga_finish_discovery opens the product and starts planning its first initiatives (paid agent work: ask the person first).";
27486
+ case "complete": return "The import is done: review the reality documents (taiga_get_product_document without type), then " + FINISH_DISCOVERY;
26907
27487
  case "failed":
26908
27488
  case "cancelled": return "The last import did not finish: taiga_start_import runs it again.";
26909
27489
  default: return "Link its repository if it has none (taiga_list_linkable_repositories, taiga_link_repository), then taiga_start_import: the import derives the documents from the code and runs by itself.";
@@ -26927,7 +27507,7 @@ const ITEM_ID_HINT = "taiga_list_initiatives lists a product's initiatives with
26927
27507
  const BY_ARGUMENT = {
26928
27508
  initiativeId: ITEM_ID_HINT,
26929
27509
  runId: "taiga_list_runs lists the runs, of one product or of every product the key can see.",
26930
- planId: "taiga_get_plan gives the initiative's active plan and its ID; taiga_list_plans lists every version's ID.",
27510
+ planId: "taiga_get_plan gives the initiative's active plan and its ID.",
26931
27511
  linkId: "taiga_list_product_repositories lists the product's repository links; a linkable repository id is not a link ID.",
26932
27512
  replacesLinkId: "taiga_list_product_repositories lists the product's repository links.",
26933
27513
  linkableRepositoryId: "taiga_list_linkable_repositories lists the repositories the GitHub and GitLab connections reach, with their ids.",
@@ -27599,11 +28179,25 @@ function withFixability(row) {
27599
28179
  if (dependency && !row["recommendedVersion"] && row["remediableBy"] === "coding_agent") return {
27600
28180
  ...row,
27601
28181
  fixable: false,
27602
- fixNote: "No fixed version is known yet: taiga_fix_finding refuses it until one is published."
28182
+ fixNote: noVersionNote(row["data"])
27603
28183
  };
27604
28184
  return row;
27605
28185
  }
27606
28186
  /**
28187
+ * Why a dependency has no version to move to. A language runtime declared as
28188
+ * a container image moves only to a release the image has published
28189
+ * (PRO-3729), so its vendor's fix can be out while Fix is refused: the
28190
+ * finding's runtime data says so where the row carries it (taiga_get_finding).
28191
+ */
28192
+ function noVersionNote(data) {
28193
+ const runtime = data?.runtime;
28194
+ const fixedIn = typeof runtime?.["fixedIn"] === "string" ? runtime["fixedIn"] : null;
28195
+ if (fixedIn) return `Fixed in ${fixedIn}, but there is no release to move to yet: the image the repository declares has not published it, or, where the line has ended, a supported line (the summary says which). taiga_fix_finding refuses it until there is one.`;
28196
+ if (runtime && (typeof runtime["newest"] === "string" || "endOfLife" in runtime)) return "A newer release is out, but the image the repository declares has not published one to move to yet (the summary names the image): taiga_fix_finding refuses it until it does.";
28197
+ if (runtime) return "No fixed release is known yet, or, where the line has ended, the image the repository declares has not published a supported line (the summary says which): taiga_fix_finding refuses it until there is one.";
28198
+ return "No version to move to yet: no fixed version is known, or for a language runtime the image the repository declares has not published one (taiga_get_finding says which). taiga_fix_finding refuses it until there is one.";
28199
+ }
28200
+ /**
27607
28201
  * Dev-only, runtime or unknown, said on a dependency row (PRO-2861) in place of the raw per-lockfile groups
27608
28202
  * the API carries: the groups need the lockfile name to read, which `dependencyScope` does once here.
27609
28203
  */
@@ -27999,7 +28593,7 @@ function registerMaintenanceTools(server, client) {
27999
28593
  }));
28000
28594
  server.registerTool("taiga_fix_finding", {
28001
28595
  title: "Fix a finding",
28002
- description: "Raise an initiative that fixes a finding; it ends in a pull request, which merges on its own only where the product's auto-merge allows it. wholeGroup: true fixes, in that repository, every open advisory on that package version in one bump, or every place the rule flagged. A malicious package is removed, with every advisory on that version, whatever wholeGroup says. Refused when no fixed version is known (fixable: false), the code is in a submodule, or a secret is only in history (rotate it outside Taiga).",
28596
+ description: "Raise an initiative that fixes a finding; it ends in a pull request, which merges on its own only where the product's auto-merge allows it. wholeGroup: true fixes, in that repository, every open advisory on that package version in one bump, or every place the rule flagged. A malicious package is removed, with every advisory on that version, whatever wholeGroup says. A language runtime moves every file declaring it together, in a container image only to a tag the image has published. Refused when there is no version to move to (fixable: false; for a runtime, also while its image has not published the fix), the code is in a submodule, or a secret is only in history (rotate it outside Taiga).",
28003
28597
  inputSchema: object({
28004
28598
  productId,
28005
28599
  findingId,
@@ -30562,57 +31156,27 @@ function registerBacklogReads(server, client) {
30562
31156
  }));
30563
31157
  server.registerTool("taiga_get_plan", {
30564
31158
  title: "Get the active plan",
30565
- description: "Read an initiative's active plan, step by step: what each builds, the files it writes and reads, and what it depends on. Enough to approve or reject it; full: true adds each step's complete instructions (long). A plan a request for changes revised says so in revision: the steps it added, edited and dropped, and the committed steps it reverts. version reads an earlier version instead (taiga_list_plans lists them): the plan comes with its verdict, who gave it and the comment, and what it answers. NOT_FOUND when there is no active plan, the initiative's situation says why; with version, when the initiative has no such version, and the message names the ones it has.",
31159
+ description: "Read an initiative's active plan, step by step: what each builds, the files it writes and reads, and what it depends on. Enough to approve or reject it; full: true adds each step's complete instructions (long). A plan a request for changes revised says so in revision: the steps it added, edited and dropped, and the committed steps it reverts. NOT_FOUND when there is no active plan, the initiative's situation says why.",
30566
31160
  inputSchema: object({
30567
31161
  initiativeId,
30568
- version: number$1().int().min(1).optional().describe("A plan version to read, such as 1 (default: the active plan); taiga_list_plans lists the versions"),
30569
31162
  full: boolean().optional().describe("Carry each step's complete instructions (default false: a summary)")
30570
31163
  }),
30571
31164
  annotations: READ_ONLY
30572
31165
  }, (params) => runTool(async () => {
30573
- let plan;
30574
- let versionNote = {};
30575
- if (params.version === void 0) plan = (await client.getActivePlan(params.initiativeId)).data;
30576
- else {
30577
- const history = (await client.listPlanHistory(params.initiativeId, "oldest")).data;
30578
- const entry = history.find((candidate) => candidate.version === params.version);
30579
- if (!entry) {
30580
- const have = history.map((candidate) => candidate.version).sort((a, b) => a - b);
30581
- return toolError("NOT_FOUND", have.length > 0 ? `This initiative has no plan version ${params.version}; it has version${have.length > 1 ? "s" : ""} ${have.join(", ")}.` : `This initiative has no plan version ${params.version}: it has never been planned.`);
30582
- }
30583
- plan = (await client.getPlan(entry.planId)).data;
30584
- versionNote = {
30585
- verdict: entry.verdict,
30586
- answers: entry.answers
30587
- };
30588
- }
31166
+ const plan = (await client.getActivePlan(params.initiativeId)).data;
30589
31167
  const revision = await planRevisionOf(client, params.initiativeId, plan.id);
30590
31168
  const revised = revision ? { revision } : {};
30591
31169
  if (params.full) return toolResult({
30592
31170
  ...plan,
30593
- ...versionNote,
30594
31171
  ...revised
30595
31172
  });
30596
31173
  const steps = Array.isArray(plan.steps) ? plan.steps : [];
30597
31174
  return toolResult({
30598
31175
  ...pickFields([plan], PLAN_SUMMARY_FIELDS)[0],
30599
- ...versionNote,
30600
31176
  ...revised,
30601
31177
  steps: pickFields(steps, PLAN_STEP_SUMMARY_FIELDS)
30602
31178
  });
30603
31179
  }));
30604
- server.registerTool("taiga_list_plans", {
30605
- title: "List plan versions and their verdicts",
30606
- description: "List every plan version of an initiative, newest first (order: 'oldest' reverses it). Each version has its status, its verdict (approved, rejected, changes_requested, awaiting_review, or none when none was recorded), who gave it by name, when and the comment, and the earlier version and comment it answers. taiga_get_plan with version reads one in full. An initiative never planned returns an empty list.",
30607
- inputSchema: object({
30608
- initiativeId,
30609
- order: _enum(["newest", "oldest"]).optional().describe("Order of the versions (default 'newest')")
30610
- }),
30611
- annotations: READ_ONLY
30612
- }, (params) => runTool(async () => {
30613
- const versions = (await client.listPlanHistory(params.initiativeId, params.order)).data;
30614
- return toolResult({ versions });
30615
- }));
30616
31180
  }
30617
31181
  function registerRequest(server, client) {
30618
31182
  server.registerTool("taiga_request_initiatives", {
@@ -48377,6 +48941,7 @@ function withStrictInputs(server, client, registered, toolsets, left) {
48377
48941
  const inputs = /* @__PURE__ */ new Map();
48378
48942
  const register = server.registerTool.bind(server);
48379
48943
  server.registerTool = ((name, config, callback) => {
48944
+ if (DELIVERY_TOOLS.has(name) && client.getIntrospection()?.deliveryIncluded === false) return void 0;
48380
48945
  const toolset = TOOLSET_OF[name];
48381
48946
  if (name !== "taiga_whoami") {
48382
48947
  if (!toolset) throw new Error(`Tool ${name}: no toolset in toolsets.ts`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taiga-ai/mcp-server",
3
- "version": "0.36.0-rc.776",
3
+ "version": "0.36.0-rc.800",
4
4
  "description": "Taiga for AI coding assistants: read products, policies, initiatives and runs, and operate the line, over MCP",
5
5
  "mcpName": "ga.tai/mcp-server",
6
6
  "license": "UNLICENSED",