deepline 0.3.88 → 0.3.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/sdk/src/client.ts +534 -4
- package/dist/bundling-sources/sdk/src/config.ts +77 -0
- package/dist/bundling-sources/sdk/src/http.ts +76 -30
- package/dist/bundling-sources/sdk/src/index.ts +6 -0
- package/dist/bundling-sources/sdk/src/monitor-fleet-contract.ts +1 -1
- package/dist/bundling-sources/sdk/src/play.ts +15 -1
- package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +2 -2
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/types.ts +83 -4
- package/dist/bundling-sources/shared_libs/integration-contracts/AGENTS.md +9 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/README.md +3 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/index.ts +2 -0
- package/dist/bundling-sources/shared_libs/monitors/analytics-install-guides.ts +77 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/charges.ts +125 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/policy-builders.ts +686 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/pricing.ts +54 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/public-pricing.ts +72 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/session.ts +45 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/state.ts +454 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/tamradar.ts +260 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/types.ts +215 -0
- package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +333 -0
- package/dist/bundling-sources/shared_libs/monitors/cursor-page.ts +42 -0
- package/dist/bundling-sources/shared_libs/monitors/deactivation-reasons.ts +16 -0
- package/dist/bundling-sources/shared_libs/monitors/framework-managed-payload-fields.ts +71 -0
- package/dist/bundling-sources/shared_libs/monitors/generated/provider-monitor-callback-admission-targets.ts +16 -0
- package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +267 -0
- package/dist/bundling-sources/shared_libs/monitors/inbound-publish-key.ts +39 -0
- package/dist/bundling-sources/shared_libs/monitors/inbound-queue.ts +82 -0
- package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +473 -0
- package/dist/bundling-sources/shared_libs/monitors/org-monitor-limits.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/package.json +29 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +1125 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +263 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-capability.ts +964 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-consumer-health.ts +56 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-errors.ts +131 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +535 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-legacy-aliases.ts +16 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-priority-execution.ts +56 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-public-aliases.ts +28 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-runtime-read-eligibility.ts +38 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-state.ts +122 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-status.ts +10 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +112 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-webhook-monitor-runtime.ts +300 -0
- package/dist/bundling-sources/shared_libs/monitors/quickstart-prompts.ts +22 -0
- package/dist/bundling-sources/shared_libs/monitors/snitcher-install-validation.ts +93 -0
- package/dist/bundling-sources/shared_libs/monitors/snitcher-ip2company.ts +332 -0
- package/dist/bundling-sources/shared_libs/monitors/snitcher-radar.ts +221 -0
- package/dist/bundling-sources/shared_libs/monitors/starter-templates.ts +105 -0
- package/dist/bundling-sources/shared_libs/monitors/tracking-provider-guidance.ts +73 -0
- package/dist/bundling-sources/shared_libs/monitors/tracking-provider-integrations.ts +81 -0
- package/dist/bundling-sources/shared_libs/monitors/tsconfig.json +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/activity-observation.ts +6 -11
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +90 -12
- package/dist/bundling-sources/shared_libs/play-runtime/async-play-invocation.ts +78 -0
- package/dist/bundling-sources/shared_libs/play-runtime/checkpoint-boundaries.ts +70 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +407 -53
- package/dist/bundling-sources/shared_libs/play-runtime/coordinator-headers.ts +1 -32
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +57 -0
- package/dist/bundling-sources/shared_libs/play-runtime/default-batch-strategies.ts +20 -1
- package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-protocol.ts +7 -1
- package/dist/bundling-sources/shared_libs/play-runtime/lane-retirement-gate.ts +189 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +28 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +23 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +18 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-start-admission.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +10 -8
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-env.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-scheduler-topology.ts +24 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +30 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +6 -3
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +454 -17
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +19 -4
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +6 -14
- package/dist/bundling-sources/shared_libs/plays/core.ts +11 -6
- package/dist/bundling-sources/shared_libs/plays/docflow-binding-owner.ts +16 -11
- package/dist/bundling-sources/shared_libs/plays/email-status.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/resolve-static-pipeline.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/slug.ts +115 -0
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +44 -14
- package/dist/bundling-sources/shared_libs/plays/tool-category-descriptions.ts +2 -2
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +877 -0
- package/dist/bundling-sources/shared_libs/product-notifications/configuration-draft.ts +456 -0
- package/dist/bundling-sources/shared_libs/product-notifications/configuration.ts +560 -0
- package/dist/bundling-sources/shared_libs/product-notifications/content.ts +28 -0
- package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +59 -0
- package/dist/bundling-sources/shared_libs/product-notifications/email.ts +246 -0
- package/dist/bundling-sources/shared_libs/product-notifications/evaluation.ts +280 -0
- package/dist/bundling-sources/shared_libs/product-notifications/events.ts +433 -0
- package/dist/bundling-sources/shared_libs/product-notifications/legacy-slack.ts +80 -0
- package/dist/bundling-sources/shared_libs/product-notifications/workspace.ts +38 -0
- package/dist/bundling-sources/shared_libs/runtime-env.ts +6 -0
- package/dist/bundling-sources/shared_libs/security/header-safe-env.ts +28 -0
- package/dist/bundling-sources/shared_libs/security/internal-actor.ts +50 -0
- package/dist/bundling-sources/shared_libs/security/secret-redaction.ts +267 -0
- package/dist/cli/index.js +1070 -193
- package/dist/cli/index.mjs +1057 -180
- package/dist/{compiler-manifest-Dbov16F7.d.mts → compiler-manifest-DsLbQaew.d.mts} +132 -8
- package/dist/{compiler-manifest-Dbov16F7.d.ts → compiler-manifest-DsLbQaew.d.ts} +132 -8
- package/dist/index.d.mts +834 -12
- package/dist/index.d.ts +834 -12
- package/dist/index.js +469 -40
- package/dist/index.mjs +469 -40
- package/dist/install-integrity.json +65 -4
- package/dist/plays/bundle-play-file.d.mts +8 -3
- package/dist/plays/bundle-play-file.d.ts +8 -3
- package/dist/plays/bundle-play-file.mjs +100 -20
- package/package.json +3 -1
- /package/dist/bundling-sources/shared_libs/{integrations/bettercontact-execution-policy.ts → integration-contracts/bettercontact/execution-policy.ts} +0 -0
- /package/dist/bundling-sources/shared_libs/{integrations/theirstack-execution-policy.ts → integration-contracts/theirstack/execution-policy.ts} +0 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -572,6 +572,7 @@ var HOST_URL_ENV = "DEEPLINE_HOST_URL";
|
|
|
572
572
|
var API_KEY_ENV = "DEEPLINE_API_KEY";
|
|
573
573
|
var ACTIVE_ORG_ID_ENV = "DEEPLINE_ACTIVE_ORG_ID";
|
|
574
574
|
var ACTIVE_ORG_NAME_ENV = "DEEPLINE_ACTIVE_ORG_NAME";
|
|
575
|
+
var FEATURES_ENV = "DEEPLINE_FEATURES";
|
|
575
576
|
var PROD_URL = "https://code.deepline.com";
|
|
576
577
|
var DEFAULT_TIMEOUT = 6e4;
|
|
577
578
|
var DEFAULT_MAX_RETRIES = 3;
|
|
@@ -596,8 +597,40 @@ var CLI_ENV_ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
|
596
597
|
HOST_URL_ENV,
|
|
597
598
|
API_KEY_ENV,
|
|
598
599
|
ACTIVE_ORG_ID_ENV,
|
|
599
|
-
ACTIVE_ORG_NAME_ENV
|
|
600
|
+
ACTIVE_ORG_NAME_ENV,
|
|
601
|
+
FEATURES_ENV
|
|
600
602
|
]);
|
|
603
|
+
function featureEnvValues(data) {
|
|
604
|
+
if (!Array.isArray(data.features)) return {};
|
|
605
|
+
return {
|
|
606
|
+
[FEATURES_ENV]: data.features.filter(
|
|
607
|
+
(key) => typeof key === "string" && key.trim() !== ""
|
|
608
|
+
).map((key) => key.trim()).join(",")
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
function storedHostApiKey(baseUrl) {
|
|
612
|
+
return loadCliEnv(normalizeBaseUrl(baseUrl) || baseUrl)[API_KEY_ENV] ?? "";
|
|
613
|
+
}
|
|
614
|
+
function storedHostFeatures(baseUrl) {
|
|
615
|
+
return loadCliEnv(normalizeBaseUrl(baseUrl) || baseUrl)[FEATURES_ENV];
|
|
616
|
+
}
|
|
617
|
+
function envHasFeature(env, feature) {
|
|
618
|
+
return (env[FEATURES_ENV] ?? "").split(",").map((key) => key.trim()).includes(feature);
|
|
619
|
+
}
|
|
620
|
+
function cliFeatureEnabled(feature) {
|
|
621
|
+
const processEnv = process.env;
|
|
622
|
+
if (envHasFeature(processEnv, feature)) return true;
|
|
623
|
+
if (processEnv[API_KEY_ENV]?.trim()) return false;
|
|
624
|
+
try {
|
|
625
|
+
const baseUrl = resolveBaseUrlOnly();
|
|
626
|
+
const projectEnv = loadProjectEnvCandidates().find(
|
|
627
|
+
({ env }) => normalizeBaseUrl(env[HOST_URL_ENV] ?? "") === baseUrl && Boolean(env[API_KEY_ENV])
|
|
628
|
+
);
|
|
629
|
+
return envHasFeature(projectEnv?.env ?? loadCliEnv(baseUrl), feature);
|
|
630
|
+
} catch {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
601
634
|
function baseUrlSlug(baseUrl) {
|
|
602
635
|
let url;
|
|
603
636
|
try {
|
|
@@ -797,6 +830,10 @@ function mergePersistedEnvValues(existing, values) {
|
|
|
797
830
|
if (nextApiKey !== void 0 && nextApiKey !== existing[API_KEY_ENV] && values[ACTIVE_ORG_ID_ENV] === void 0) {
|
|
798
831
|
delete merged[ACTIVE_ORG_ID_ENV];
|
|
799
832
|
delete merged[ACTIVE_ORG_NAME_ENV];
|
|
833
|
+
delete merged[FEATURES_ENV];
|
|
834
|
+
}
|
|
835
|
+
if (values[FEATURES_ENV] === "") {
|
|
836
|
+
delete merged[FEATURES_ENV];
|
|
800
837
|
}
|
|
801
838
|
return merged;
|
|
802
839
|
}
|
|
@@ -920,7 +957,10 @@ function resolveConfig(options) {
|
|
|
920
957
|
apiKey,
|
|
921
958
|
baseUrl,
|
|
922
959
|
timeout: options?.timeout ?? DEFAULT_TIMEOUT,
|
|
923
|
-
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES
|
|
960
|
+
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,
|
|
961
|
+
// Pass through untouched: the transport owns case-insensitive merging so
|
|
962
|
+
// there is exactly one place that decides which header wins.
|
|
963
|
+
...options?.headers ? { headers: { ...options.headers } } : {}
|
|
924
964
|
};
|
|
925
965
|
}
|
|
926
966
|
function mergeProjectEnvFile(filePath, values) {
|
|
@@ -1210,7 +1250,7 @@ var SDK_RELEASE = {
|
|
|
1210
1250
|
// available at toolResponse.rawV2 while toolResponse.raw and all declared
|
|
1211
1251
|
// getters keep their established compatibility behavior.
|
|
1212
1252
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1213
|
-
version: "0.3.
|
|
1253
|
+
version: "0.3.89",
|
|
1214
1254
|
updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
|
|
1215
1255
|
packageCapabilities: {
|
|
1216
1256
|
updatePreferences: 1
|
|
@@ -1764,11 +1804,33 @@ function normalizeRequestAbortError(error, input2) {
|
|
|
1764
1804
|
}
|
|
1765
1805
|
return normalized;
|
|
1766
1806
|
}
|
|
1807
|
+
function applyExplicitHeaders(headers, explicit) {
|
|
1808
|
+
if (!explicit) return headers;
|
|
1809
|
+
for (const [rawName, value] of Object.entries(explicit)) {
|
|
1810
|
+
const name = rawName.trim().toLowerCase();
|
|
1811
|
+
if (!name) continue;
|
|
1812
|
+
for (const existing of Object.keys(headers)) {
|
|
1813
|
+
if (existing.toLowerCase() === name) delete headers[existing];
|
|
1814
|
+
}
|
|
1815
|
+
headers[name] = value;
|
|
1816
|
+
}
|
|
1817
|
+
return headers;
|
|
1818
|
+
}
|
|
1767
1819
|
function isAbortLikeError(error) {
|
|
1768
1820
|
const name = error.name.toLowerCase();
|
|
1769
1821
|
const message = error.message.toLowerCase();
|
|
1770
1822
|
return name === "aborterror" || message.includes("operation was aborted") || message === "aborted";
|
|
1771
1823
|
}
|
|
1824
|
+
function withErrorCause(error, cause) {
|
|
1825
|
+
if (cause !== null && cause !== void 0) {
|
|
1826
|
+
Object.defineProperty(error, "cause", {
|
|
1827
|
+
value: cause,
|
|
1828
|
+
configurable: true,
|
|
1829
|
+
writable: true
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
return error;
|
|
1833
|
+
}
|
|
1772
1834
|
function mapNetworkError(baseUrl, error, targetLabel2) {
|
|
1773
1835
|
const tagged = error;
|
|
1774
1836
|
const timeoutMs = tagged?.[REQUEST_TIMEOUT_MARKER];
|
|
@@ -1885,7 +1947,7 @@ var HttpClient = class {
|
|
|
1885
1947
|
if (coordinatorInternalToken?.trim() && (coordinatorUrl?.trim() || workerCallbackUrl?.trim() || runtimeTestFault?.trim() || absurdReleaseOverride?.trim() || preferredReceiptGatewayMachineId?.trim())) {
|
|
1886
1948
|
headers[COORDINATOR_INTERNAL_TOKEN_HEADER] = coordinatorInternalToken.trim();
|
|
1887
1949
|
}
|
|
1888
|
-
return headers;
|
|
1950
|
+
return applyExplicitHeaders(headers, this.config.headers);
|
|
1889
1951
|
}
|
|
1890
1952
|
/**
|
|
1891
1953
|
* Send an HTTP request with automatic retries and error handling.
|
|
@@ -2039,32 +2101,38 @@ var HttpClient = class {
|
|
|
2039
2101
|
);
|
|
2040
2102
|
if (options?.toolId) {
|
|
2041
2103
|
const code = mappedNetworkError.code;
|
|
2042
|
-
throw
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2104
|
+
throw withErrorCause(
|
|
2105
|
+
new ToolExecutionError(
|
|
2106
|
+
withCoworkNetworkHint(mappedNetworkError.message),
|
|
2107
|
+
{
|
|
2108
|
+
toolId: options.toolId,
|
|
2109
|
+
provider: providerLabelFromToolId(options.toolId),
|
|
2110
|
+
operation: options.toolId,
|
|
2111
|
+
code,
|
|
2112
|
+
origin: "deepline",
|
|
2113
|
+
category: "network",
|
|
2114
|
+
// A direct client timeout has ambiguous delivery. Fail closed unless
|
|
2115
|
+
// the server returns the authoritative action delivery contract.
|
|
2116
|
+
retryable: false,
|
|
2117
|
+
statusCode: null,
|
|
2118
|
+
requestId: null,
|
|
2119
|
+
retryAfterMs: null,
|
|
2120
|
+
networkKind: code === "NETWORK_TIMEOUT" ? "timeout" : code === "NETWORK_ABORTED" ? "unknown" : "unavailable",
|
|
2121
|
+
networkScope: "client_to_deepline",
|
|
2122
|
+
details: mappedNetworkError.details
|
|
2123
|
+
}
|
|
2124
|
+
),
|
|
2125
|
+
lastError
|
|
2061
2126
|
);
|
|
2062
2127
|
}
|
|
2063
|
-
throw
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2128
|
+
throw withErrorCause(
|
|
2129
|
+
new DeeplineError(
|
|
2130
|
+
withCoworkNetworkHint(mappedNetworkError.message),
|
|
2131
|
+
void 0,
|
|
2132
|
+
mappedNetworkError.code,
|
|
2133
|
+
mappedNetworkError.details
|
|
2134
|
+
),
|
|
2135
|
+
lastError
|
|
2068
2136
|
);
|
|
2069
2137
|
}
|
|
2070
2138
|
/**
|
|
@@ -2438,6 +2506,13 @@ var PRODUCT_NOTIFICATION_DELIVERY_LEASE_MS = 2 * 6e4;
|
|
|
2438
2506
|
var PRODUCT_NOTIFICATION_SUCCESS_TTL_MS = 15 * 6e4;
|
|
2439
2507
|
var PRODUCT_NOTIFICATION_FAILURE_TTL_MS = 24 * 60 * 6e4;
|
|
2440
2508
|
|
|
2509
|
+
// ../product-notifications/configuration.ts
|
|
2510
|
+
var PRODUCT_NOTIFICATION_EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2511
|
+
function normalizeProductNotificationEmail(value) {
|
|
2512
|
+
const email = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
2513
|
+
return email && email.length <= 320 && PRODUCT_NOTIFICATION_EMAIL_PATTERN.test(email) ? email : null;
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2441
2516
|
// src/stream-reconnect.ts
|
|
2442
2517
|
var STREAM_RECONNECT_BASE_DELAY_MS = 500;
|
|
2443
2518
|
var STREAM_RECONNECT_MAX_DELAY_MS = 15e3;
|
|
@@ -2966,7 +3041,7 @@ function isRecord4(value) {
|
|
|
2966
3041
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
2967
3042
|
}
|
|
2968
3043
|
function isPlayActivityObservation(value) {
|
|
2969
|
-
if (!isRecord4(value) || value.schemaVersion !== 1 || typeof value.activityId !== "string" || !value.activityId.trim() || typeof value.observedAt !== "number" || !Number.isFinite(value.observedAt) || !isRecord4(value.target) || !isRecord4(value.state)) {
|
|
3044
|
+
if (!isRecord4(value) || value.schemaVersion !== void 0 && value.schemaVersion !== 1 || typeof value.activityId !== "string" || !value.activityId.trim() || typeof value.observedAt !== "number" || !Number.isFinite(value.observedAt) || !isRecord4(value.target) || !isRecord4(value.state)) {
|
|
2970
3045
|
return false;
|
|
2971
3046
|
}
|
|
2972
3047
|
const targetKinds = /* @__PURE__ */ new Set([
|
|
@@ -3073,7 +3148,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3073
3148
|
if (input2.waitKind === "detached_runner") {
|
|
3074
3149
|
return projection(
|
|
3075
3150
|
{
|
|
3076
|
-
schemaVersion: 1,
|
|
3077
3151
|
activityId: "runner:managed",
|
|
3078
3152
|
target: {
|
|
3079
3153
|
kind: "runner",
|
|
@@ -3089,7 +3163,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3089
3163
|
if (input2.waitKind === "sleep") {
|
|
3090
3164
|
return projection(
|
|
3091
3165
|
{
|
|
3092
|
-
schemaVersion: 1,
|
|
3093
3166
|
activityId: "run:sleep",
|
|
3094
3167
|
target: {
|
|
3095
3168
|
kind: "step",
|
|
@@ -3109,7 +3182,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3109
3182
|
if (input2.waitKind === "integration_event" || input2.waitKind === "integration_event_batch") {
|
|
3110
3183
|
return projection(
|
|
3111
3184
|
{
|
|
3112
|
-
schemaVersion: 1,
|
|
3113
3185
|
activityId: `event:${input2.activeNodeId ?? "run"}`,
|
|
3114
3186
|
stepId: input2.activeNodeId ?? void 0,
|
|
3115
3187
|
target: {
|
|
@@ -3133,7 +3205,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3133
3205
|
if (normalizedStatus === "waiting") {
|
|
3134
3206
|
return projection(
|
|
3135
3207
|
{
|
|
3136
|
-
schemaVersion: 1,
|
|
3137
3208
|
activityId: "run:legacy-wait",
|
|
3138
3209
|
target: {
|
|
3139
3210
|
kind: "step",
|
|
@@ -3160,7 +3231,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3160
3231
|
const datasetProgress = datasetStep?.progress ?? null;
|
|
3161
3232
|
return projection(
|
|
3162
3233
|
{
|
|
3163
|
-
schemaVersion: 1,
|
|
3164
3234
|
activityId: `dataset:${pendingDataset.datasetId ?? pendingDataset.tableNamespace}`,
|
|
3165
3235
|
target: {
|
|
3166
3236
|
kind: "dataset",
|
|
@@ -3188,7 +3258,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3188
3258
|
const provider = toolId?.split(/[._]/)[0]?.trim() || null;
|
|
3189
3259
|
return projection(
|
|
3190
3260
|
{
|
|
3191
|
-
schemaVersion: 1,
|
|
3192
3261
|
activityId: `step:${activeStep.nodeId}`,
|
|
3193
3262
|
stepId: activeStep.nodeId,
|
|
3194
3263
|
target: toolId && provider ? {
|
|
@@ -3213,7 +3282,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3213
3282
|
if (normalizedStatus === "queued") {
|
|
3214
3283
|
return projection(
|
|
3215
3284
|
{
|
|
3216
|
-
schemaVersion: 1,
|
|
3217
3285
|
activityId: "capacity:worker",
|
|
3218
3286
|
target: { kind: "capacity", pool: "worker" },
|
|
3219
3287
|
state: { kind: "queued", reason: "capacity" },
|
|
@@ -3223,7 +3291,6 @@ function projectPlayRunActivity(input2) {
|
|
|
3223
3291
|
);
|
|
3224
3292
|
}
|
|
3225
3293
|
const fallback = {
|
|
3226
|
-
schemaVersion: 1,
|
|
3227
3294
|
activityId: "run:legacy",
|
|
3228
3295
|
target: {
|
|
3229
3296
|
kind: "step",
|
|
@@ -4338,7 +4405,7 @@ async function* observeRunEvents(options) {
|
|
|
4338
4405
|
}
|
|
4339
4406
|
}
|
|
4340
4407
|
|
|
4341
|
-
//
|
|
4408
|
+
// ../integration-contracts/theirstack/execution-policy.ts
|
|
4342
4409
|
var THEIRSTACK_SLOW_JOB_SEARCH_PROVIDER_TIMEOUT_MS = 135e3;
|
|
4343
4410
|
var THEIRSTACK_SLOW_JOB_SEARCH_CLIENT_TIMEOUT_MS = 6e4 + THEIRSTACK_SLOW_JOB_SEARCH_PROVIDER_TIMEOUT_MS + 15e3;
|
|
4344
4411
|
var THEIRSTACK_COMPANY_SEARCH_CLIENT_TIMEOUT_MS = 21e4;
|
|
@@ -4392,7 +4459,7 @@ function resolveTheirstackClientTimeoutMs(endpointId, payload) {
|
|
|
4392
4459
|
return usesExtendedTheirstackJobSearchBudget(endpointId, payload) ? THEIRSTACK_SLOW_JOB_SEARCH_CLIENT_TIMEOUT_MS : null;
|
|
4393
4460
|
}
|
|
4394
4461
|
|
|
4395
|
-
//
|
|
4462
|
+
// ../integration-contracts/bettercontact/execution-policy.ts
|
|
4396
4463
|
var BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS = 12e4;
|
|
4397
4464
|
var BETTERCONTACT_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
4398
4465
|
"bettercontact_enrich",
|
|
@@ -4483,6 +4550,42 @@ function providerMetaFromToolResponseRawV2(rawV2, view) {
|
|
|
4483
4550
|
}
|
|
4484
4551
|
|
|
4485
4552
|
// src/client.ts
|
|
4553
|
+
var MAX_NOTIFICATION_GROUP_CREATE_TARGETS = 50;
|
|
4554
|
+
function parseNotificationGroupTarget(value) {
|
|
4555
|
+
const normalized = value.trim();
|
|
4556
|
+
if (normalized.toLowerCase().startsWith("email:")) {
|
|
4557
|
+
const email = normalizeProductNotificationEmail(normalized.slice(6));
|
|
4558
|
+
if (!email) {
|
|
4559
|
+
throw new Error(
|
|
4560
|
+
`Invalid email notification target "${value}". Use --to email:name@example.com.`
|
|
4561
|
+
);
|
|
4562
|
+
}
|
|
4563
|
+
return { kind: "email", email };
|
|
4564
|
+
}
|
|
4565
|
+
const slack = /^slack:(.+)$/i.exec(normalized)?.[1]?.trim();
|
|
4566
|
+
if (!slack) {
|
|
4567
|
+
const provider = normalized.split(":", 1)[0] || normalized;
|
|
4568
|
+
throw new Error(
|
|
4569
|
+
`Unsupported notification destination "${provider}". Use email: or slack:.`
|
|
4570
|
+
);
|
|
4571
|
+
}
|
|
4572
|
+
const member = /^member:([UW][A-Z0-9]{8,})$/i.exec(slack);
|
|
4573
|
+
if (member?.[1]) {
|
|
4574
|
+
return { kind: "slack", memberId: member[1].toUpperCase() };
|
|
4575
|
+
}
|
|
4576
|
+
if (slack.toLowerCase().startsWith("member:")) {
|
|
4577
|
+
throw new Error(
|
|
4578
|
+
"Slack member IDs must look like slack:member:U0123456789."
|
|
4579
|
+
);
|
|
4580
|
+
}
|
|
4581
|
+
if (!slack.replace(/^#/, "").trim()) {
|
|
4582
|
+
throw new Error("Use --to slack:#channel.");
|
|
4583
|
+
}
|
|
4584
|
+
return { kind: "slack", channel: slack };
|
|
4585
|
+
}
|
|
4586
|
+
function notificationObjectKey(kind) {
|
|
4587
|
+
return `${kind}.${globalThis.crypto.randomUUID()}`;
|
|
4588
|
+
}
|
|
4486
4589
|
var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
4487
4590
|
var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
|
|
4488
4591
|
var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
|
|
@@ -5052,6 +5155,10 @@ var DeeplineClient = class {
|
|
|
5052
5155
|
audit: (options2) => this.auditMonitors(options2),
|
|
5053
5156
|
repair: (options2) => this.repairMonitors(options2),
|
|
5054
5157
|
health: (options2) => this.readMonitorsHealth(options2),
|
|
5158
|
+
batch: {
|
|
5159
|
+
submit: (options2) => this.submitMonitorBatch(options2),
|
|
5160
|
+
get: (operationId, options2) => this.getMonitorBatch(operationId, options2)
|
|
5161
|
+
},
|
|
5055
5162
|
fleets: {
|
|
5056
5163
|
sync: (definitionOrId, options2) => this.syncMonitorFleet(definitionOrId, options2),
|
|
5057
5164
|
get: (fleetId, options2) => fleetId === void 0 ? this.listMonitorFleets() : this.getMonitorFleet(fleetId, options2),
|
|
@@ -5184,6 +5291,16 @@ var DeeplineClient = class {
|
|
|
5184
5291
|
(secret) => secret.name === normalized && secret.status === "active" && secret.hasValue
|
|
5185
5292
|
) ?? null;
|
|
5186
5293
|
}
|
|
5294
|
+
/** Check effective scope and active-version health without reading the value.
|
|
5295
|
+
* Without playName, checks the organization-scoped secret only. With a Play
|
|
5296
|
+
* name, an active Play secret takes precedence; a deleted/disabled Play
|
|
5297
|
+
* secret falls back to the organization-scoped secret.
|
|
5298
|
+
*/
|
|
5299
|
+
async inspectSecret(name, options = {}) {
|
|
5300
|
+
const params = new URLSearchParams({ name: name.trim().toUpperCase() });
|
|
5301
|
+
if (options.playName !== void 0) params.set("play", options.playName);
|
|
5302
|
+
return this.http.get(`/api/v2/secrets?${params.toString()}`);
|
|
5303
|
+
}
|
|
5187
5304
|
// ——————————————————————————————————————————————————————————
|
|
5188
5305
|
// Tools
|
|
5189
5306
|
// ——————————————————————————————————————————————————————————
|
|
@@ -5275,6 +5392,10 @@ var DeeplineClient = class {
|
|
|
5275
5392
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/get`,
|
|
5276
5393
|
{
|
|
5277
5394
|
method: "GET",
|
|
5395
|
+
// Tool metadata is a read-only catalog lookup. Keep the metadata
|
|
5396
|
+
// header while opting into the same transient edge-response retries as
|
|
5397
|
+
// other GET catalog methods such as searchTools().
|
|
5398
|
+
retryApiErrors: true,
|
|
5278
5399
|
headers: {
|
|
5279
5400
|
"x-deepline-tool-meta-only": "1"
|
|
5280
5401
|
}
|
|
@@ -6730,6 +6851,197 @@ var DeeplineClient = class {
|
|
|
6730
6851
|
async getNotifications() {
|
|
6731
6852
|
return this.http.get("/api/v2/notifications");
|
|
6732
6853
|
}
|
|
6854
|
+
/** Read the group-based product-notification configuration and rule catalog. */
|
|
6855
|
+
async getNotificationConfiguration() {
|
|
6856
|
+
return this.http.get("/api/v2/notifications/configuration");
|
|
6857
|
+
}
|
|
6858
|
+
/** Atomically apply one retry-safe desired configuration change. */
|
|
6859
|
+
async changeNotificationConfiguration(expectedWorkspaceVersion, change) {
|
|
6860
|
+
return this.http.put("/api/v2/notifications/configuration", {
|
|
6861
|
+
expectedWorkspaceVersion,
|
|
6862
|
+
change
|
|
6863
|
+
});
|
|
6864
|
+
}
|
|
6865
|
+
/** Create one notification group and its destinations as a retry-safe unit. */
|
|
6866
|
+
async createNotificationGroup(input2) {
|
|
6867
|
+
const name = input2.name.trim().replace(/\s+/g, " ");
|
|
6868
|
+
if (!name) throw new Error("Notification group name is required.");
|
|
6869
|
+
if (input2.targets.length < 1 || input2.targets.length > MAX_NOTIFICATION_GROUP_CREATE_TARGETS) {
|
|
6870
|
+
throw new Error(
|
|
6871
|
+
`Choose between 1 and ${MAX_NOTIFICATION_GROUP_CREATE_TARGETS} notification targets.`
|
|
6872
|
+
);
|
|
6873
|
+
}
|
|
6874
|
+
const targets = input2.targets.map(parseNotificationGroupTarget);
|
|
6875
|
+
const legacyEvents = input2.legacyEvents ?? [];
|
|
6876
|
+
const legacyTarget = targets.length === 1 && targets[0]?.kind === "slack" && legacyEvents.length > 0 ? targets[0] : null;
|
|
6877
|
+
if (legacyEvents.length > 0 && !legacyTarget) {
|
|
6878
|
+
throw new Error(
|
|
6879
|
+
"--for is supported only by the legacy one-Slack-target form. Create the group first, then add rules in notification configuration."
|
|
6880
|
+
);
|
|
6881
|
+
}
|
|
6882
|
+
if (!legacyTarget && name.toLowerCase() === "default") {
|
|
6883
|
+
throw new Error(
|
|
6884
|
+
"Default is reserved for the workspace default notification group."
|
|
6885
|
+
);
|
|
6886
|
+
}
|
|
6887
|
+
const normalizedTargets = targets.map(
|
|
6888
|
+
(target) => target.kind === "email" ? `email:${target.email}` : "memberId" in target ? `slack:member:${target.memberId}` : `slack:${target.channel}`
|
|
6889
|
+
);
|
|
6890
|
+
if (input2.dryRun) {
|
|
6891
|
+
return {
|
|
6892
|
+
mode: "dry_run",
|
|
6893
|
+
compatibilityMode: legacyTarget !== null,
|
|
6894
|
+
name: legacyTarget ? input2.name : name,
|
|
6895
|
+
targets: normalizedTargets,
|
|
6896
|
+
legacyEvents
|
|
6897
|
+
};
|
|
6898
|
+
}
|
|
6899
|
+
if (legacyTarget) {
|
|
6900
|
+
const notification = await this.createNotification({
|
|
6901
|
+
name: input2.name,
|
|
6902
|
+
provider: "slack",
|
|
6903
|
+
..."channel" in legacyTarget ? { channel: legacyTarget.channel } : { memberId: legacyTarget.memberId },
|
|
6904
|
+
eventTypes: legacyEvents
|
|
6905
|
+
});
|
|
6906
|
+
return { mode: "legacy", notification };
|
|
6907
|
+
}
|
|
6908
|
+
const current = await this.getNotificationConfiguration();
|
|
6909
|
+
const existingGroup = current.configuration.groups.find(
|
|
6910
|
+
(candidate) => candidate.name.toLowerCase() === name.toLowerCase()
|
|
6911
|
+
);
|
|
6912
|
+
const groupKey = existingGroup?.groupKey ?? notificationObjectKey("group");
|
|
6913
|
+
const group = existingGroup ?? {
|
|
6914
|
+
groupKey,
|
|
6915
|
+
name,
|
|
6916
|
+
enabled: true,
|
|
6917
|
+
deliveryTiming: { mode: "immediate" },
|
|
6918
|
+
source: "workspace",
|
|
6919
|
+
configMode: "custom",
|
|
6920
|
+
version: 0
|
|
6921
|
+
};
|
|
6922
|
+
const destinations = current.configuration.destinations.filter(
|
|
6923
|
+
(destination) => destination.groupKey === groupKey
|
|
6924
|
+
);
|
|
6925
|
+
const emails = [
|
|
6926
|
+
...new Set(
|
|
6927
|
+
targets.flatMap(
|
|
6928
|
+
(target) => target.kind === "email" ? [target.email] : []
|
|
6929
|
+
)
|
|
6930
|
+
)
|
|
6931
|
+
].sort();
|
|
6932
|
+
const existingEmails = new Set(
|
|
6933
|
+
destinations.flatMap(
|
|
6934
|
+
(destination) => destination.settings.kind === "email_addresses" ? destination.settings.to : []
|
|
6935
|
+
)
|
|
6936
|
+
);
|
|
6937
|
+
const newEmails = emails.filter((email) => !existingEmails.has(email));
|
|
6938
|
+
if (newEmails.length > 0) {
|
|
6939
|
+
destinations.push({
|
|
6940
|
+
destinationKey: notificationObjectKey("destination"),
|
|
6941
|
+
groupKey,
|
|
6942
|
+
name: "Email recipients",
|
|
6943
|
+
enabled: true,
|
|
6944
|
+
source: "workspace",
|
|
6945
|
+
configMode: "custom",
|
|
6946
|
+
version: 0,
|
|
6947
|
+
status: "active",
|
|
6948
|
+
settings: { kind: "email_addresses", to: newEmails }
|
|
6949
|
+
});
|
|
6950
|
+
}
|
|
6951
|
+
const slackTargets = /* @__PURE__ */ new Map();
|
|
6952
|
+
for (const target of targets) {
|
|
6953
|
+
if (target.kind !== "slack") continue;
|
|
6954
|
+
const targetKey = "memberId" in target ? `member:${target.memberId}` : `channel:${target.channel.replace(/^#/, "").toLowerCase()}`;
|
|
6955
|
+
slackTargets.set(targetKey, target);
|
|
6956
|
+
}
|
|
6957
|
+
const connectionId = current.slackConnection.connectionId;
|
|
6958
|
+
if (slackTargets.size > 0 && !connectionId) {
|
|
6959
|
+
throw new Error(
|
|
6960
|
+
"Slack is not connected to this workspace. Connect it in Dashboard \u2192 Integrations, then retry."
|
|
6961
|
+
);
|
|
6962
|
+
}
|
|
6963
|
+
const resolvedSlackTargets = await Promise.all(
|
|
6964
|
+
[...slackTargets.values()].map(async (target) => {
|
|
6965
|
+
if ("memberId" in target) {
|
|
6966
|
+
return {
|
|
6967
|
+
targetKind: "member",
|
|
6968
|
+
targetId: target.memberId,
|
|
6969
|
+
targetName: target.memberId
|
|
6970
|
+
};
|
|
6971
|
+
}
|
|
6972
|
+
const channel = target.channel;
|
|
6973
|
+
const requested = channel.replace(/^#/, "");
|
|
6974
|
+
const response = await this.listNotificationChannels(channel);
|
|
6975
|
+
const matches = response.channels.filter(
|
|
6976
|
+
(candidate) => candidate.id === requested || candidate.name.toLowerCase() === requested.toLowerCase()
|
|
6977
|
+
);
|
|
6978
|
+
if (matches.length !== 1) {
|
|
6979
|
+
throw new Error(
|
|
6980
|
+
matches.length === 0 ? `Slack channel ${channel} was not found or is not visible to the Deepline app.` : `Slack channel ${channel} is ambiguous. Use its channel ID.`
|
|
6981
|
+
);
|
|
6982
|
+
}
|
|
6983
|
+
return {
|
|
6984
|
+
targetKind: "channel",
|
|
6985
|
+
targetId: matches[0].id,
|
|
6986
|
+
targetName: matches[0].name
|
|
6987
|
+
};
|
|
6988
|
+
})
|
|
6989
|
+
);
|
|
6990
|
+
const uniqueSlackTargets = new Map(
|
|
6991
|
+
resolvedSlackTargets.map((target) => [
|
|
6992
|
+
`${target.targetKind}:${target.targetId}`,
|
|
6993
|
+
target
|
|
6994
|
+
])
|
|
6995
|
+
);
|
|
6996
|
+
for (const target of uniqueSlackTargets.values()) {
|
|
6997
|
+
if (destinations.some(
|
|
6998
|
+
(destination) => destination.settings.kind === "slack" && destination.settings.targetKind === target.targetKind && destination.settings.targetId === target.targetId
|
|
6999
|
+
)) {
|
|
7000
|
+
continue;
|
|
7001
|
+
}
|
|
7002
|
+
destinations.push({
|
|
7003
|
+
destinationKey: notificationObjectKey("destination"),
|
|
7004
|
+
groupKey,
|
|
7005
|
+
name: `${target.targetKind === "channel" ? "#" : "@"}${target.targetName}`,
|
|
7006
|
+
enabled: true,
|
|
7007
|
+
source: "workspace",
|
|
7008
|
+
configMode: "custom",
|
|
7009
|
+
version: 0,
|
|
7010
|
+
status: "pending_verification",
|
|
7011
|
+
settings: {
|
|
7012
|
+
kind: "slack",
|
|
7013
|
+
...target,
|
|
7014
|
+
oauthConnectionId: connectionId
|
|
7015
|
+
}
|
|
7016
|
+
});
|
|
7017
|
+
}
|
|
7018
|
+
const draft = {
|
|
7019
|
+
group,
|
|
7020
|
+
destinations,
|
|
7021
|
+
rules: current.configuration.rules.filter(
|
|
7022
|
+
(rule) => rule.groupKey === groupKey
|
|
7023
|
+
)
|
|
7024
|
+
};
|
|
7025
|
+
const result = await this.changeNotificationConfiguration(
|
|
7026
|
+
current.configuration.workspaceVersion,
|
|
7027
|
+
{ kind: "save_group", draft }
|
|
7028
|
+
);
|
|
7029
|
+
const storedGroup = result.configuration.groups.find(
|
|
7030
|
+
(candidate) => candidate.groupKey === groupKey
|
|
7031
|
+
);
|
|
7032
|
+
if (!storedGroup) {
|
|
7033
|
+
throw new Error("Notification group creation returned no saved group.");
|
|
7034
|
+
}
|
|
7035
|
+
return {
|
|
7036
|
+
mode: "native",
|
|
7037
|
+
groupKey,
|
|
7038
|
+
targets: normalizedTargets,
|
|
7039
|
+
group: storedGroup,
|
|
7040
|
+
destinations: result.configuration.destinations.filter(
|
|
7041
|
+
(destination) => destination.groupKey === groupKey
|
|
7042
|
+
)
|
|
7043
|
+
};
|
|
7044
|
+
}
|
|
6733
7045
|
/** List Slack channels available to an already-connected Slack integration. */
|
|
6734
7046
|
async listNotificationChannels(query) {
|
|
6735
7047
|
const suffix = query ? `?search=${encodeURIComponent(query)}` : "";
|
|
@@ -7274,6 +7586,78 @@ var DeeplineClient = class {
|
|
|
7274
7586
|
{ method: "GET" }
|
|
7275
7587
|
);
|
|
7276
7588
|
}
|
|
7589
|
+
/** Submit durable monitor work; transport retries use the same idempotency key. */
|
|
7590
|
+
async submitMonitorBatch(options) {
|
|
7591
|
+
const idempotencyKey = options.idempotencyKey.trim();
|
|
7592
|
+
if (!idempotencyKey) {
|
|
7593
|
+
throw new DeeplineError(
|
|
7594
|
+
"Monitor batch idempotencyKey is required.",
|
|
7595
|
+
void 0,
|
|
7596
|
+
"INVALID_MONITOR_BATCH_IDEMPOTENCY_KEY"
|
|
7597
|
+
);
|
|
7598
|
+
}
|
|
7599
|
+
if (options.kind === "deploy") {
|
|
7600
|
+
if (!options.manifestNdjson.trim()) {
|
|
7601
|
+
throw new DeeplineError(
|
|
7602
|
+
"Monitor batch deploy requires a non-empty NDJSON manifest.",
|
|
7603
|
+
void 0,
|
|
7604
|
+
"INVALID_MONITOR_BATCH_MANIFEST"
|
|
7605
|
+
);
|
|
7606
|
+
}
|
|
7607
|
+
return this.http.request(
|
|
7608
|
+
"/api/v2/monitors/batch",
|
|
7609
|
+
{
|
|
7610
|
+
method: "POST",
|
|
7611
|
+
body: {
|
|
7612
|
+
kind: "deploy",
|
|
7613
|
+
manifest_ndjson: options.manifestNdjson,
|
|
7614
|
+
dry_run: options.dryRun === true,
|
|
7615
|
+
idempotency_key: idempotencyKey
|
|
7616
|
+
},
|
|
7617
|
+
headers: { "Idempotency-Key": idempotencyKey },
|
|
7618
|
+
maxRetries: 0,
|
|
7619
|
+
exactUrlOnly: true
|
|
7620
|
+
}
|
|
7621
|
+
);
|
|
7622
|
+
}
|
|
7623
|
+
const scope = options.scope.kind === "keys" ? { kind: "keys", monitor_keys: options.scope.monitorKeys } : options.scope.kind === "fleet" ? { kind: "fleet", fleet_id: options.scope.fleetId } : { kind: "target", target: options.scope.target };
|
|
7624
|
+
return this.http.request(
|
|
7625
|
+
"/api/v2/monitors/batch",
|
|
7626
|
+
{
|
|
7627
|
+
method: "POST",
|
|
7628
|
+
body: {
|
|
7629
|
+
kind: options.kind,
|
|
7630
|
+
scope,
|
|
7631
|
+
dry_run: options.dryRun === true,
|
|
7632
|
+
idempotency_key: idempotencyKey,
|
|
7633
|
+
...options.deactivationReason === void 0 ? {} : { deactivation_reason: options.deactivationReason }
|
|
7634
|
+
},
|
|
7635
|
+
headers: { "Idempotency-Key": idempotencyKey },
|
|
7636
|
+
// Durable submission is itself idempotent, but an ambiguous local retry
|
|
7637
|
+
// must retain the exact key and never turn a CLI attempt into two runs.
|
|
7638
|
+
maxRetries: 0,
|
|
7639
|
+
exactUrlOnly: true
|
|
7640
|
+
}
|
|
7641
|
+
);
|
|
7642
|
+
}
|
|
7643
|
+
/** Get durable batch progress and a bounded retained evidence page. */
|
|
7644
|
+
async getMonitorBatch(operationId, options) {
|
|
7645
|
+
const runId = operationId.trim();
|
|
7646
|
+
if (!runId) {
|
|
7647
|
+
throw new DeeplineError(
|
|
7648
|
+
"Monitor batch operation id is required.",
|
|
7649
|
+
void 0,
|
|
7650
|
+
"INVALID_MONITOR_BATCH_OPERATION_ID"
|
|
7651
|
+
);
|
|
7652
|
+
}
|
|
7653
|
+
const params = new URLSearchParams();
|
|
7654
|
+
if (options?.cursor) params.set("cursor", options.cursor);
|
|
7655
|
+
const suffix = params.size > 0 ? `?${params}` : "";
|
|
7656
|
+
return this.http.request(
|
|
7657
|
+
`/api/v2/monitors/batch/${encodeURIComponent(runId)}${suffix}`,
|
|
7658
|
+
{ method: "GET" }
|
|
7659
|
+
);
|
|
7660
|
+
}
|
|
7277
7661
|
/**
|
|
7278
7662
|
* The deployable monitor tools catalog. Pass a tool id (positional or
|
|
7279
7663
|
* `{ tool }`) to describe one tool's full payload/stream contract, or no tool
|
|
@@ -8591,7 +8975,9 @@ function saveEnvValues(values, baseUrl, scope) {
|
|
|
8591
8975
|
...values[HOST_URL_ENV] ? { [HOST_URL_ENV]: values[HOST_URL_ENV] } : {},
|
|
8592
8976
|
...values[API_KEY_ENV] ? { [API_KEY_ENV]: values[API_KEY_ENV] } : {},
|
|
8593
8977
|
...values[ACTIVE_ORG_ID_ENV] ? { [ACTIVE_ORG_ID_ENV]: values[ACTIVE_ORG_ID_ENV] } : {},
|
|
8594
|
-
...Object.prototype.hasOwnProperty.call(values, ACTIVE_ORG_NAME_ENV) ? { [ACTIVE_ORG_NAME_ENV]: values[ACTIVE_ORG_NAME_ENV] } : {}
|
|
8978
|
+
...Object.prototype.hasOwnProperty.call(values, ACTIVE_ORG_NAME_ENV) ? { [ACTIVE_ORG_NAME_ENV]: values[ACTIVE_ORG_NAME_ENV] } : {},
|
|
8979
|
+
// An explicit empty list must reach the store: it clears a stale line.
|
|
8980
|
+
...Object.prototype.hasOwnProperty.call(values, FEATURES_ENV) ? { [FEATURES_ENV]: values[FEATURES_ENV] } : {}
|
|
8595
8981
|
};
|
|
8596
8982
|
if (scope === "folder") {
|
|
8597
8983
|
saveProjectDeeplineEnvValues(filtered);
|
|
@@ -8605,7 +8991,8 @@ function activeOrgEnvValues(data) {
|
|
|
8605
8991
|
const orgName = typeof data.org_name === "string" ? data.org_name.trim() : "";
|
|
8606
8992
|
return {
|
|
8607
8993
|
[ACTIVE_ORG_ID_ENV]: orgId,
|
|
8608
|
-
[ACTIVE_ORG_NAME_ENV]: orgName
|
|
8994
|
+
[ACTIVE_ORG_NAME_ENV]: orgName,
|
|
8995
|
+
...featureEnvValues(data)
|
|
8609
8996
|
};
|
|
8610
8997
|
}
|
|
8611
8998
|
async function httpJson(method, url, apiKey, body, timeoutMs = AUTH_HTTP_TIMEOUT_MS) {
|
|
@@ -9130,6 +9517,8 @@ async function handleStatus(args) {
|
|
|
9130
9517
|
savedApiKeyPath = envFilePath(baseUrl);
|
|
9131
9518
|
}
|
|
9132
9519
|
}
|
|
9520
|
+
} else if (resolvedAuthScope === "folder" || storedHostApiKey(baseUrl) === apiKey) {
|
|
9521
|
+
saveEnvValues(featureEnvValues(data), baseUrl, resolvedAuthScope);
|
|
9133
9522
|
}
|
|
9134
9523
|
printCommandEnvelope(
|
|
9135
9524
|
{
|
|
@@ -10334,12 +10723,12 @@ async function handleBuyCredits(creditsRaw, options) {
|
|
|
10334
10723
|
);
|
|
10335
10724
|
}
|
|
10336
10725
|
async function handleTargetPlan(planSku, options) {
|
|
10337
|
-
if (planSku !== "payg-v1" && planSku !== "builder-v1" && planSku !== "team-v1") {
|
|
10726
|
+
if (planSku !== "payg-v1" && planSku !== "builder-v1" && planSku !== "growth-v1" && planSku !== "growth-canary-v1" && planSku !== "team-v1") {
|
|
10338
10727
|
reportBillingFailure(
|
|
10339
10728
|
{
|
|
10340
10729
|
exitCode: 2,
|
|
10341
10730
|
code: "INVALID_PLAN",
|
|
10342
|
-
message: "Plan must be payg-v1, builder-v1, or team-v1."
|
|
10731
|
+
message: "Plan must be payg-v1, builder-v1, growth-v1, growth-canary-v1, or team-v1."
|
|
10343
10732
|
},
|
|
10344
10733
|
options
|
|
10345
10734
|
);
|
|
@@ -10600,7 +10989,7 @@ Examples:
|
|
|
10600
10989
|
"Disable automatic recharge without clearing saved amounts."
|
|
10601
10990
|
).option("--idempotency-key <key>", "Stable retry key").option("--dry-run", "Print the planned update without applying it").option("--json", "Emit JSON output").action(handleAutoRechargeOff)
|
|
10602
10991
|
);
|
|
10603
|
-
billing.command("change-plan").description("Start or change the target billing plan.").argument("<plan_sku>", "payg-v1, builder-v1, or team-v1").option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleTargetPlan);
|
|
10992
|
+
billing.command("change-plan").description("Start or change the target billing plan.").argument("<plan_sku>", "payg-v1, builder-v1, growth-v1, growth-canary-v1, or team-v1").option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleTargetPlan);
|
|
10604
10993
|
billing.command("cancel-plan").description("Cancel a target subscription at period end, or undo it.").option("--undo", "Undo a pending period-end cancellation").option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleTargetPlanCancellation);
|
|
10605
10994
|
billing.command("portal").description("Open the Stripe-hosted billing recovery portal.").option("--no-open", "Print the URL without opening a browser").option("--json", "Emit JSON output").action(handleTargetPortal);
|
|
10606
10995
|
billing.command("plans").description("Show published plans and the plan you are on.").addHelpText(
|
|
@@ -10894,6 +11283,12 @@ function mergeCanonicalRowsInfo(left, right) {
|
|
|
10894
11283
|
const exportUnavailableReason = left.exportUnavailableReason === "shared_table_namespace" || right.exportUnavailableReason === "shared_table_namespace" ? "shared_table_namespace" : left.exportUnavailableReason ?? right.exportUnavailableReason;
|
|
10895
11284
|
const unavailableSource = left.exportUnavailableReason === exportUnavailableReason ? left : right.exportUnavailableReason === exportUnavailableReason ? right : null;
|
|
10896
11285
|
const columns = preferred.columns.length > 0 ? preferred.columns : fallback.columns;
|
|
11286
|
+
const recoveredReturnPaths2 = [
|
|
11287
|
+
.../* @__PURE__ */ new Set([
|
|
11288
|
+
...left.recoveredReturnPaths ?? [],
|
|
11289
|
+
...right.recoveredReturnPaths ?? []
|
|
11290
|
+
])
|
|
11291
|
+
];
|
|
10897
11292
|
return {
|
|
10898
11293
|
...fallback,
|
|
10899
11294
|
...preferred,
|
|
@@ -10906,6 +11301,7 @@ function mergeCanonicalRowsInfo(left, right) {
|
|
|
10906
11301
|
datasetId: preferred.datasetId ?? fallback.datasetId,
|
|
10907
11302
|
tableNamespace: preferred.tableNamespace ?? fallback.tableNamespace,
|
|
10908
11303
|
...left.recovered || right.recovered ? { recovered: true } : {},
|
|
11304
|
+
...recoveredReturnPaths2.length ? { recoveredReturnPaths: recoveredReturnPaths2 } : {},
|
|
10909
11305
|
...exportUnavailableReason ? {
|
|
10910
11306
|
exportUnavailableReason,
|
|
10911
11307
|
...unavailableSource?.exportUnavailableMessage ? {
|
|
@@ -10966,6 +11362,16 @@ function isSerializedDataset(value) {
|
|
|
10966
11362
|
function isPackagedDatasetOutput(value) {
|
|
10967
11363
|
return isRecord8(value) && value.kind === "dataset" && isRecord8(value.preview) && Array.isArray(value.preview.rows);
|
|
10968
11364
|
}
|
|
11365
|
+
function recoveredReturnPaths(value) {
|
|
11366
|
+
if (!Array.isArray(value)) return [];
|
|
11367
|
+
return [
|
|
11368
|
+
...new Set(
|
|
11369
|
+
value.filter(
|
|
11370
|
+
(path) => typeof path === "string" && /^result\.[A-Za-z_$][A-Za-z0-9_$]*$/.test(path)
|
|
11371
|
+
).slice(0, 200)
|
|
11372
|
+
)
|
|
11373
|
+
];
|
|
11374
|
+
}
|
|
10969
11375
|
function pathParts(path) {
|
|
10970
11376
|
return path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
10971
11377
|
}
|
|
@@ -11062,6 +11468,11 @@ function canonicalRowsInfoFromCandidate(input2) {
|
|
|
11062
11468
|
datasetId: typeof candidate.value.datasetId === "string" ? candidate.value.datasetId : null,
|
|
11063
11469
|
tableNamespace: typeof candidate.value.tableNamespace === "string" ? candidate.value.tableNamespace : null,
|
|
11064
11470
|
...candidate.value.recovered === true ? { recovered: true } : {},
|
|
11471
|
+
...recoveredReturnPaths(candidate.value.recoveredReturnPaths).length ? {
|
|
11472
|
+
recoveredReturnPaths: recoveredReturnPaths(
|
|
11473
|
+
candidate.value.recoveredReturnPaths
|
|
11474
|
+
)
|
|
11475
|
+
} : {},
|
|
11065
11476
|
...isRecord8(candidate.value.exportUnavailable) && (candidate.value.exportUnavailable.reason === "empty_dataset" || candidate.value.exportUnavailable.reason === "shared_table_namespace") ? {
|
|
11066
11477
|
exportUnavailableReason: candidate.value.exportUnavailable.reason,
|
|
11067
11478
|
...typeof candidate.value.exportUnavailable.message === "string" ? {
|
|
@@ -15217,6 +15628,82 @@ var PLAY_AUTHORING_FIELD_REGISTRY = {
|
|
|
15217
15628
|
description: "Unsupported legacy child-workflow timeout.",
|
|
15218
15629
|
errorMessage: "ctx.runPlay timeoutMs is unsupported because child Plays execute inline."
|
|
15219
15630
|
},
|
|
15631
|
+
"ctx.runPlayAsync.key": {
|
|
15632
|
+
schema: Type.String({ minLength: 1 }),
|
|
15633
|
+
fixtures: {
|
|
15634
|
+
valid: "request-approval",
|
|
15635
|
+
invalid: "",
|
|
15636
|
+
absent: void 0,
|
|
15637
|
+
unresolved: { expression: "callKey" },
|
|
15638
|
+
edition1: "request-approval"
|
|
15639
|
+
},
|
|
15640
|
+
referenceType: "string",
|
|
15641
|
+
required: true,
|
|
15642
|
+
resolution: "runtime-dynamic",
|
|
15643
|
+
issueCode: "play_authoring_run_play_option_invalid",
|
|
15644
|
+
description: "Stable identity for one independent child Play Run.",
|
|
15645
|
+
errorMessage: "ctx.runPlayAsync key must be a non-empty string."
|
|
15646
|
+
},
|
|
15647
|
+
"ctx.runPlayAsync.playRef": {
|
|
15648
|
+
schema: Type.Union([
|
|
15649
|
+
Type.String({ minLength: 1 }),
|
|
15650
|
+
Type.Union([
|
|
15651
|
+
Type.Object(
|
|
15652
|
+
{ playName: Type.String({ minLength: 1 }) },
|
|
15653
|
+
{ additionalProperties: true }
|
|
15654
|
+
),
|
|
15655
|
+
Type.Object(
|
|
15656
|
+
{ name: Type.String({ minLength: 1 }) },
|
|
15657
|
+
{ additionalProperties: true }
|
|
15658
|
+
)
|
|
15659
|
+
])
|
|
15660
|
+
]),
|
|
15661
|
+
fixtures: {
|
|
15662
|
+
valid: "request-approval",
|
|
15663
|
+
invalid: {},
|
|
15664
|
+
absent: void 0,
|
|
15665
|
+
unresolved: { expression: "playRef" },
|
|
15666
|
+
edition1: "request-approval"
|
|
15667
|
+
},
|
|
15668
|
+
referenceType: "string | PlayReferenceLike",
|
|
15669
|
+
required: true,
|
|
15670
|
+
resolution: "runtime-dynamic",
|
|
15671
|
+
issueCode: "play_authoring_run_play_option_invalid",
|
|
15672
|
+
description: "Independently published scalar child Play name or strongly typed definition handle.",
|
|
15673
|
+
errorMessage: "ctx.runPlayAsync playRef must be a non-empty Play name or definition handle."
|
|
15674
|
+
},
|
|
15675
|
+
"ctx.runPlayAsync.input": {
|
|
15676
|
+
schema: Type.Record(Type.String(), Type.Unknown()),
|
|
15677
|
+
fixtures: {
|
|
15678
|
+
valid: { draftId: "draft-1" },
|
|
15679
|
+
invalid: "draft-1",
|
|
15680
|
+
absent: void 0,
|
|
15681
|
+
unresolved: "childInput",
|
|
15682
|
+
edition1: {}
|
|
15683
|
+
},
|
|
15684
|
+
referenceType: "Record<string, unknown>",
|
|
15685
|
+
required: true,
|
|
15686
|
+
resolution: "runtime-dynamic",
|
|
15687
|
+
issueCode: "play_authoring_run_play_option_invalid",
|
|
15688
|
+
description: "Scalar input object submitted to the independent child Run.",
|
|
15689
|
+
errorMessage: "ctx.runPlayAsync input must be an object."
|
|
15690
|
+
},
|
|
15691
|
+
"ctx.runPlayAsync.options.description": {
|
|
15692
|
+
schema: Type.String({ minLength: 1 }),
|
|
15693
|
+
fixtures: {
|
|
15694
|
+
valid: "Request approval.",
|
|
15695
|
+
invalid: "",
|
|
15696
|
+
absent: void 0,
|
|
15697
|
+
unresolved: { expression: "description" },
|
|
15698
|
+
edition1: "Request approval."
|
|
15699
|
+
},
|
|
15700
|
+
referenceType: "string",
|
|
15701
|
+
required: true,
|
|
15702
|
+
resolution: "runtime-dynamic",
|
|
15703
|
+
issueCode: "play_authoring_run_play_option_invalid",
|
|
15704
|
+
description: "Non-empty purpose for one independent child Play Run.",
|
|
15705
|
+
errorMessage: "ctx.runPlayAsync options.description must be non-empty."
|
|
15706
|
+
},
|
|
15220
15707
|
"runtime.timeout": {
|
|
15221
15708
|
schema: Type.String({ pattern: "^\\d+\\s*[mh]$" }),
|
|
15222
15709
|
fixtures: {
|
|
@@ -15504,6 +15991,10 @@ var PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
|
|
|
15504
15991
|
`export type CsvOptions = { description?: ${cloudReferenceType("ctx.csv.options.description")}; columns?: ${cloudReferenceType("ctx.csv.options.columns")}; rename?: ${cloudReferenceType("ctx.csv.options.rename")}; required?: ${cloudReferenceType("ctx.csv.options.required")} };`,
|
|
15505
15992
|
"export type PlayCallExecution = 'inline';",
|
|
15506
15993
|
`export type PlayCallOptions = { description: ${cloudReferenceType("ctx.runPlay.options.description")}; execution?: ${cloudReferenceType("ctx.runPlay.options.execution")}; timeoutMs?: ${cloudReferenceType("ctx.runPlay.options.timeoutMs")} };`,
|
|
15994
|
+
`export type PlayAsyncCallOptions = { description: ${cloudReferenceType("ctx.runPlayAsync.options.description")} };`,
|
|
15995
|
+
"declare const PLAY_RUN_ID_BRAND: unique symbol;",
|
|
15996
|
+
"export type PlayRunId = string & { readonly [PLAY_RUN_ID_BRAND]: 'PlayRunId' };",
|
|
15997
|
+
"export type AsyncPlayRunRef = Readonly<{ runId: PlayRunId }>;",
|
|
15507
15998
|
`export type RuntimeStepOptions = { semanticKey?: ${cloudReferenceType("ctx.step.semanticKey")}; staleAfterSeconds?: ${cloudReferenceType("ctx.step.staleAfterSeconds")} };`,
|
|
15508
15999
|
`export type FetchOptions = { staleAfterSeconds?: ${cloudReferenceType("ctx.fetch.staleAfterSeconds")}; transient?: boolean };`,
|
|
15509
16000
|
"export type PlayFetchResponse = { ok: boolean; status: number; statusText: string; url: string; headers: Record<string, string>; bodyText: string; json: unknown | null };",
|
|
@@ -15529,11 +16020,11 @@ var PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
|
|
|
15529
16020
|
" withColumn<Name extends string, Value>(name: Name, definition: DatasetColumnDefinition<OutputRow, Value> & { readonly runIf: (row: OutputRow, index: number) => boolean | Promise<boolean> }): DatasetBuilder<InputRow, OutputRow & Record<Name, Value | null>>;",
|
|
15530
16021
|
" withColumn<Name extends string, Value>(name: Name, definition: DatasetColumnDefinition<OutputRow, Value>): DatasetBuilder<InputRow, OutputRow & Record<Name, Value>>;",
|
|
15531
16022
|
" withColumn<Name extends string, Value>(name: Name, resolver: StepResolver<OutputRow, Value> | RunnableColumnStepProgram<Value>, options: StepOptions<OutputRow, Value>): DatasetBuilder<InputRow, OutputRow & Record<Name, Value | null>>;",
|
|
15532
|
-
" withColumns<
|
|
16023
|
+
" withColumns<ProgramOutput extends OutputRow, Return>(program: StepProgram<OutputRow, ProgramOutput, Return>): DatasetBuilder<InputRow, ProgramOutput>;",
|
|
15533
16024
|
" step<Name extends string, Value>(name: Name, resolver: ColumnResolver<OutputRow, Value>): never;",
|
|
15534
16025
|
" run(options?: DatasetRunOptions<InputRow>): Promise<PlayDataset<OutputRow>>;",
|
|
15535
16026
|
"};",
|
|
15536
|
-
"export type PlayReferenceLike = { readonly playName: string; readonly name?: string } | { readonly name: string; readonly playName?: string };",
|
|
16027
|
+
"export type PlayReferenceLike<TInput extends Record<string, unknown> = Record<string, unknown>> = ({ readonly playName: string; readonly name?: string } | { readonly name: string; readonly playName?: string }) & { readonly __inputType?: TInput };",
|
|
15537
16028
|
"export interface DeeplinePlayRuntimeContext {",
|
|
15538
16029
|
" csv<T = Record<string, unknown>>(path: string | CsvInput<T & object>, options?: CsvOptions): Promise<PlayDataset<T>>;",
|
|
15539
16030
|
" dataset<TSource extends PlayDatasetInput<object>>(key: string, items: TSource): DatasetBuilder<PlayDatasetRow<TSource> & object, PlayDatasetRow<TSource> & object>;",
|
|
@@ -15547,6 +16038,8 @@ var PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
|
|
|
15547
16038
|
" fetch(key: string, url: string | URL, init?: RequestInit & { headers?: HeadersInit & { 'Idempotency-Key'?: string; 'X-Idempotency-Key'?: string }; auth?: SecretAuthInput }, options?: FetchOptions): Promise<PlayFetchResponse>;",
|
|
15548
16039
|
" secrets: { get(name: string): SecretPromise; bearer(secret: string | SecretPromise | SecretHandle): SecretAuth; header(header: string, secret: string | SecretPromise | SecretHandle): SecretAuth };",
|
|
15549
16040
|
` runPlay<TOutput = unknown>(key: string, playRef: ${cloudReferenceType("ctx.runPlay.playRef")}, input: ${cloudReferenceType("ctx.runPlay.input")}, options: PlayCallOptions): Promise<TOutput>;`,
|
|
16041
|
+
" runPlayAsync<TInput extends Record<string, unknown>>(key: string, playRef: PlayReferenceLike<TInput>, input: NoInfer<TInput>, options: PlayAsyncCallOptions): Promise<AsyncPlayRunRef>;",
|
|
16042
|
+
" runPlayAsync(key: string, playRef: string, input: Record<string, unknown>, options: PlayAsyncCallOptions): Promise<AsyncPlayRunRef>;",
|
|
15550
16043
|
" log(message: string, options?: { level?: 'debug' | 'info' | 'warn' | 'error' }): void;",
|
|
15551
16044
|
` sleep(ms: ${cloudReferenceType("ctx.sleep.ms")}): Promise<void>;`,
|
|
15552
16045
|
"}",
|
|
@@ -15821,7 +16314,7 @@ function collectInlineSecretFindings(sourceCode) {
|
|
|
15821
16314
|
var MAX_PLAY_BUNDLE_BYTES = 30 * 1024 * 1024;
|
|
15822
16315
|
|
|
15823
16316
|
// ../plays/bundling/index.ts
|
|
15824
|
-
var PLAY_BUNDLE_CACHE_VERSION =
|
|
16317
|
+
var PLAY_BUNDLE_CACHE_VERSION = 37;
|
|
15825
16318
|
var PLAY_ARTIFACT_CACHE_DIR = join7(
|
|
15826
16319
|
tmpdir2(),
|
|
15827
16320
|
`deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION}`
|
|
@@ -16560,7 +17053,7 @@ var RunDataset = class _RunDataset {
|
|
|
16560
17053
|
return this.#info.exportUnavailableMessage;
|
|
16561
17054
|
}
|
|
16562
17055
|
matches(path) {
|
|
16563
|
-
return this.source === path || this.datasetId === path || this.tableNamespace === path;
|
|
17056
|
+
return this.source === path || this.datasetId === path || this.tableNamespace === path || this.#info.recoveredReturnPaths?.includes(path) === true;
|
|
16564
17057
|
}
|
|
16565
17058
|
/** Return a new Handle when its preview has been replaced by fetched rows. */
|
|
16566
17059
|
withRows(info) {
|
|
@@ -17070,7 +17563,7 @@ function resolveDaytonaSandboxComputeItem(input2) {
|
|
|
17070
17563
|
};
|
|
17071
17564
|
}
|
|
17072
17565
|
|
|
17073
|
-
//
|
|
17566
|
+
// ../billing/compute-pricing-contract.ts
|
|
17074
17567
|
var COMPUTE_BILLING_MARKUP_MULTIPLIER = 5;
|
|
17075
17568
|
var DEFAULT_USD_PER_CUSTOMER_CREDIT = 0.1;
|
|
17076
17569
|
var DEFAULT_PROVIDER_MARKUP_MULTIPLIER = 1.4;
|
|
@@ -17405,6 +17898,39 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
17405
17898
|
"--open",
|
|
17406
17899
|
"--debug-map-latency"
|
|
17407
17900
|
]);
|
|
17901
|
+
var PLAY_RUN_HEADER_FLAG_USAGE = `--header requires "<name>: <value>", for example: --header 'x-deepline-absurd-release: 2026-09-07.1'`;
|
|
17902
|
+
var HTTP_HEADER_NAME_PATTERN = /^[!#$%&'*+\-.^_`|~0-9a-z]+$/;
|
|
17903
|
+
function parsePlayRunHeaderFlag(raw) {
|
|
17904
|
+
const separator = raw.indexOf(":");
|
|
17905
|
+
if (separator < 0) {
|
|
17906
|
+
throw new Error(
|
|
17907
|
+
`${PLAY_RUN_HEADER_FLAG_USAGE}. Got ${JSON.stringify(raw)} with no ":" separator.`
|
|
17908
|
+
);
|
|
17909
|
+
}
|
|
17910
|
+
const name = raw.slice(0, separator).trim().toLowerCase();
|
|
17911
|
+
const value = raw.slice(separator + 1).trim();
|
|
17912
|
+
if (!name) {
|
|
17913
|
+
throw new Error(
|
|
17914
|
+
`${PLAY_RUN_HEADER_FLAG_USAGE}. Got ${JSON.stringify(raw)} with an empty header name.`
|
|
17915
|
+
);
|
|
17916
|
+
}
|
|
17917
|
+
if (!HTTP_HEADER_NAME_PATTERN.test(name)) {
|
|
17918
|
+
throw new Error(
|
|
17919
|
+
`${PLAY_RUN_HEADER_FLAG_USAGE}. ${JSON.stringify(name)} is not a valid HTTP header name.`
|
|
17920
|
+
);
|
|
17921
|
+
}
|
|
17922
|
+
if (!value) {
|
|
17923
|
+
throw new Error(
|
|
17924
|
+
`${PLAY_RUN_HEADER_FLAG_USAGE}. Header ${JSON.stringify(name)} was given an empty value.`
|
|
17925
|
+
);
|
|
17926
|
+
}
|
|
17927
|
+
if (/[\u0000-\u001f\u007f]/.test(value)) {
|
|
17928
|
+
throw new Error(
|
|
17929
|
+
`${PLAY_RUN_HEADER_FLAG_USAGE}. Header ${JSON.stringify(name)} contains a control character.`
|
|
17930
|
+
);
|
|
17931
|
+
}
|
|
17932
|
+
return { name, value };
|
|
17933
|
+
}
|
|
17408
17934
|
function isBarePlayRunDebugFlag(args, index) {
|
|
17409
17935
|
return args[index] === "--debug" && (args[index + 1] === void 0 || args[index + 1].startsWith("--"));
|
|
17410
17936
|
}
|
|
@@ -19018,6 +19544,9 @@ function assertPlayWaitNotTimedOut(input2) {
|
|
|
19018
19544
|
}
|
|
19019
19545
|
}
|
|
19020
19546
|
var PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS = 15e3;
|
|
19547
|
+
function isAdmittedRunVisibilityDelay(error) {
|
|
19548
|
+
return error instanceof DeeplineError && error.statusCode === 404 && error.message.trim() === "Workflow run not found.";
|
|
19549
|
+
}
|
|
19021
19550
|
async function waitForPlayCompletionByStream(input2) {
|
|
19022
19551
|
let lastPhase = null;
|
|
19023
19552
|
let reconnectAttempt = 0;
|
|
@@ -19031,7 +19560,7 @@ async function waitForPlayCompletionByStream(input2) {
|
|
|
19031
19560
|
billing: false
|
|
19032
19561
|
});
|
|
19033
19562
|
} catch (error) {
|
|
19034
|
-
if (isTransientPlayStreamError(error)) {
|
|
19563
|
+
if (isTransientPlayStreamError(error) || isAdmittedRunVisibilityDelay(error)) {
|
|
19035
19564
|
return null;
|
|
19036
19565
|
}
|
|
19037
19566
|
throw error;
|
|
@@ -19142,7 +19671,7 @@ async function waitForPlayCompletionByStream(input2) {
|
|
|
19142
19671
|
if (timedOut) {
|
|
19143
19672
|
return { kind: "timed_out", sawEvent };
|
|
19144
19673
|
}
|
|
19145
|
-
if (!isTransientPlayStreamError(error)) {
|
|
19674
|
+
if (!isTransientPlayStreamError(error) && !isAdmittedRunVisibilityDelay(error)) {
|
|
19146
19675
|
throw error;
|
|
19147
19676
|
}
|
|
19148
19677
|
return {
|
|
@@ -21378,7 +21907,7 @@ function writeStartedPlayRun(input2) {
|
|
|
21378
21907
|
);
|
|
21379
21908
|
}
|
|
21380
21909
|
function parsePlayRunOptions(args) {
|
|
21381
|
-
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
|
|
21910
|
+
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n --header '<name>: <value>' may repeat; each is sent on every request for this run.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
|
|
21382
21911
|
let filePath = null;
|
|
21383
21912
|
let playName = null;
|
|
21384
21913
|
let input2 = null;
|
|
@@ -21399,8 +21928,20 @@ function parsePlayRunOptions(args) {
|
|
|
21399
21928
|
let profile = null;
|
|
21400
21929
|
let fixtureBehavior = null;
|
|
21401
21930
|
let runIdFile = null;
|
|
21931
|
+
let headers = null;
|
|
21402
21932
|
for (let index = 0; index < args.length; index += 1) {
|
|
21403
21933
|
const arg = args[index];
|
|
21934
|
+
if (arg === "--header" || arg.startsWith("--header=")) {
|
|
21935
|
+
const raw = arg === "--header" ? args[index + 1] : arg.slice("--header=".length);
|
|
21936
|
+
if (raw === void 0 || arg === "--header" && raw.startsWith("--")) {
|
|
21937
|
+
throw new Error(`${PLAY_RUN_HEADER_FLAG_USAGE}. No value was given.`);
|
|
21938
|
+
}
|
|
21939
|
+
const header = parsePlayRunHeaderFlag(raw);
|
|
21940
|
+
headers ??= {};
|
|
21941
|
+
headers[header.name] = header.value;
|
|
21942
|
+
if (arg === "--header") index += 1;
|
|
21943
|
+
continue;
|
|
21944
|
+
}
|
|
21404
21945
|
if (arg === "--file" && args[index + 1]) {
|
|
21405
21946
|
filePath = args[++index];
|
|
21406
21947
|
continue;
|
|
@@ -21639,7 +22180,8 @@ function parsePlayRunOptions(args) {
|
|
|
21639
22180
|
profile,
|
|
21640
22181
|
debugMapLatency,
|
|
21641
22182
|
fixtureBehavior,
|
|
21642
|
-
runIdFile
|
|
22183
|
+
runIdFile,
|
|
22184
|
+
headers
|
|
21643
22185
|
};
|
|
21644
22186
|
}
|
|
21645
22187
|
function parsePlayCheckOptions(args) {
|
|
@@ -22395,11 +22937,14 @@ function printPlayCheckOutcomes(outcomes, target) {
|
|
|
22395
22937
|
printPlayCheckOutcome(outcome, target, `[${outcome.exportName}] `);
|
|
22396
22938
|
}
|
|
22397
22939
|
}
|
|
22940
|
+
function playRunClientOptions(options) {
|
|
22941
|
+
return options.headers ? { headers: options.headers } : void 0;
|
|
22942
|
+
}
|
|
22398
22943
|
async function handleFileBackedRun(options, hooks) {
|
|
22399
22944
|
if (options.target.kind !== "file") {
|
|
22400
22945
|
throw new Error("Expected a file-backed play run target.");
|
|
22401
22946
|
}
|
|
22402
|
-
const client2 = new DeeplineClient();
|
|
22947
|
+
const client2 = new DeeplineClient(playRunClientOptions(options));
|
|
22403
22948
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
22404
22949
|
const absolutePlayPath = resolve11(options.target.path);
|
|
22405
22950
|
progress.phase("compiling play");
|
|
@@ -22607,7 +23152,7 @@ async function handleNamedRun(options, hooks) {
|
|
|
22607
23152
|
if (options.target.kind !== "name") {
|
|
22608
23153
|
throw new Error("Expected a named play run target.");
|
|
22609
23154
|
}
|
|
22610
|
-
const client2 = new DeeplineClient();
|
|
23155
|
+
const client2 = new DeeplineClient(playRunClientOptions(options));
|
|
22611
23156
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
22612
23157
|
const playName = options.target.name;
|
|
22613
23158
|
const runtimeInput = options.input ? { ...options.input } : {};
|
|
@@ -32702,7 +33247,7 @@ function renderDeployedListText(payload, requestedStatus) {
|
|
|
32702
33247
|
}
|
|
32703
33248
|
const applied = asString(payload.status_filter_applied) ?? requestedStatus ?? "active";
|
|
32704
33249
|
lines.push(
|
|
32705
|
-
`Status filter: ${applied}${requestedStatus === void 0 && applied === "active" ? " (default)" : ""} \u2014 use --status all to include
|
|
33250
|
+
`Status filter: ${applied}${requestedStatus === void 0 && applied === "active" ? " (default)" : ""} \u2014 use --status all to include inactive monitors.`
|
|
32706
33251
|
);
|
|
32707
33252
|
const summary = Array.isArray(payload.status_summary) ? payload.status_summary.flatMap((raw) => {
|
|
32708
33253
|
const item = asRecord2(raw);
|
|
@@ -32710,7 +33255,7 @@ function renderDeployedListText(payload, requestedStatus) {
|
|
|
32710
33255
|
const count = item ? asFiniteNumber(item.count) : void 0;
|
|
32711
33256
|
return status && count !== void 0 ? [`${status}: ${count}`] : [];
|
|
32712
33257
|
}).join(" ") : "";
|
|
32713
|
-
if (summary) lines.push(`All
|
|
33258
|
+
if (summary) lines.push(`All monitor states: ${summary}`);
|
|
32714
33259
|
if (payload.has_more === true || payload.is_truncated === true) {
|
|
32715
33260
|
const nextCursor = asString(payload.next_cursor);
|
|
32716
33261
|
lines.push(
|
|
@@ -33799,6 +34344,9 @@ async function handleMonitorsReactivate(key, options) {
|
|
|
33799
34344
|
}
|
|
33800
34345
|
var MONITOR_VERB_POLL_INTERVAL_MS = 2e3;
|
|
33801
34346
|
function monitorHealthLine(health) {
|
|
34347
|
+
if (health.refresh?.state === "running") {
|
|
34348
|
+
return `refreshing whole scope \xB7 scanned ${health.scanned} so far`;
|
|
34349
|
+
}
|
|
33802
34350
|
return [
|
|
33803
34351
|
`converged ${health.converged}/${health.scanned}`,
|
|
33804
34352
|
`needs_repair ${health.needs_repair}`,
|
|
@@ -33837,7 +34385,9 @@ async function watchMonitorHealth(input2) {
|
|
|
33837
34385
|
let last = await input2.client.monitors.health(scope);
|
|
33838
34386
|
input2.onProgress(last);
|
|
33839
34387
|
while (Date.now() < deadlineAt) {
|
|
33840
|
-
if (last.needs_repair === 0 && last.observed.unknown === 0)
|
|
34388
|
+
if (last.refresh?.state !== "running" && last.needs_repair === 0 && last.observed.unknown === 0) {
|
|
34389
|
+
return last;
|
|
34390
|
+
}
|
|
33841
34391
|
await new Promise(
|
|
33842
34392
|
(resolve21) => setTimeout(resolve21, MONITOR_VERB_POLL_INTERVAL_MS)
|
|
33843
34393
|
);
|
|
@@ -33847,11 +34397,21 @@ async function watchMonitorHealth(input2) {
|
|
|
33847
34397
|
return last;
|
|
33848
34398
|
}
|
|
33849
34399
|
function monitorHealthText(health) {
|
|
33850
|
-
const partial = health.truncated ? " (partial \u2014 scope larger than one read)" : "";
|
|
34400
|
+
const partial = health.refresh?.state === "running" ? " (refreshing \u2014 counts below are not final)" : health.truncated ? " (partial \u2014 scope larger than one read)" : "";
|
|
33851
34401
|
const lines = [
|
|
33852
34402
|
`scope: ${health.scope.fleet_id ?? "workspace"}${partial}`,
|
|
33853
34403
|
monitorHealthLine(health)
|
|
33854
34404
|
];
|
|
34405
|
+
if ((health.batch_operations?.length ?? 0) > 0) {
|
|
34406
|
+
lines.push("");
|
|
34407
|
+
lines.push("batch work in progress:");
|
|
34408
|
+
for (const operation of health.batch_operations ?? []) {
|
|
34409
|
+
const retry = operation.next_attempt_at === void 0 ? "" : ` \xB7 next ${new Date(operation.next_attempt_at).toISOString()}`;
|
|
34410
|
+
lines.push(
|
|
34411
|
+
` ${operation.kind} ${operation.run_id} \xB7 ${operation.state}${retry}`
|
|
34412
|
+
);
|
|
34413
|
+
}
|
|
34414
|
+
}
|
|
33855
34415
|
if (health.deactivation_reasons.length > 0) {
|
|
33856
34416
|
lines.push("");
|
|
33857
34417
|
lines.push("deactivated by Deepline:");
|
|
@@ -33924,78 +34484,143 @@ async function handleMonitorsAudit(options) {
|
|
|
33924
34484
|
);
|
|
33925
34485
|
}
|
|
33926
34486
|
async function handleMonitorsRepair(options) {
|
|
33927
|
-
|
|
34487
|
+
return await handleMonitorBatch("repair", {
|
|
34488
|
+
...options,
|
|
34489
|
+
...options.fleet?.trim() ? {} : { target: "needs-repair" }
|
|
34490
|
+
});
|
|
34491
|
+
}
|
|
34492
|
+
async function handleMonitorsHealth(options) {
|
|
33928
34493
|
const fleetId = options.fleet?.trim() || void 0;
|
|
33929
|
-
const
|
|
33930
|
-
|
|
33931
|
-
|
|
33932
|
-
|
|
34494
|
+
const health = await new DeeplineClient().monitors.health(
|
|
34495
|
+
fleetId ? { fleetId } : {}
|
|
34496
|
+
);
|
|
34497
|
+
printCommandEnvelope(health, {
|
|
34498
|
+
json: options.json,
|
|
34499
|
+
text: monitorHealthText(health)
|
|
33933
34500
|
});
|
|
33934
|
-
|
|
33935
|
-
|
|
33936
|
-
|
|
33937
|
-
|
|
34501
|
+
}
|
|
34502
|
+
function monitorBatchScope(options, kind) {
|
|
34503
|
+
const selectors = [
|
|
34504
|
+
options.target ? "target" : null,
|
|
34505
|
+
options.fleet?.trim() ? "fleet" : null,
|
|
34506
|
+
options.keys?.trim() ? "keys" : null
|
|
34507
|
+
].filter((value) => value !== null);
|
|
34508
|
+
if (selectors.length === 0 && kind === "audit") {
|
|
34509
|
+
return { kind: "target", target: "all" };
|
|
34510
|
+
}
|
|
34511
|
+
if (selectors.length !== 1) {
|
|
34512
|
+
throw new MonitorsUsageError(
|
|
34513
|
+
`monitors batch ${kind} needs exactly one selector: --target, --fleet, or --keys.`
|
|
33938
34514
|
);
|
|
33939
34515
|
}
|
|
33940
|
-
|
|
33941
|
-
if (options.
|
|
33942
|
-
|
|
33943
|
-
|
|
33944
|
-
|
|
33945
|
-
|
|
33946
|
-
|
|
33947
|
-
|
|
33948
|
-
onProgress: progress.report
|
|
33949
|
-
});
|
|
33950
|
-
} finally {
|
|
33951
|
-
progress.finish();
|
|
33952
|
-
}
|
|
34516
|
+
if (options.target) return { kind: "target", target: options.target };
|
|
34517
|
+
if (options.fleet?.trim())
|
|
34518
|
+
return { kind: "fleet", fleetId: options.fleet.trim() };
|
|
34519
|
+
const monitorKeys = (options.keys ?? "").split(",").map((key) => key.trim()).filter(Boolean);
|
|
34520
|
+
if (monitorKeys.length === 0) {
|
|
34521
|
+
throw new MonitorsUsageError(
|
|
34522
|
+
"--keys needs one or more comma-separated monitor keys."
|
|
34523
|
+
);
|
|
33953
34524
|
}
|
|
33954
|
-
|
|
33955
|
-
|
|
33956
|
-
|
|
33957
|
-
|
|
33958
|
-
|
|
33959
|
-
|
|
33960
|
-
|
|
33961
|
-
|
|
34525
|
+
return { kind: "keys", monitorKeys };
|
|
34526
|
+
}
|
|
34527
|
+
function monitorBatchIdempotencyKey(kind, value) {
|
|
34528
|
+
return value?.trim() || `monitor-batch-${kind}-${randomUUID5()}`;
|
|
34529
|
+
}
|
|
34530
|
+
async function handleMonitorBatchDeploy(options) {
|
|
34531
|
+
if (!options.file?.trim()) {
|
|
34532
|
+
throw new MonitorsUsageError(
|
|
34533
|
+
"monitors batch deploy requires --file <monitors.ndjson>."
|
|
33962
34534
|
);
|
|
33963
34535
|
}
|
|
33964
|
-
if (
|
|
33965
|
-
|
|
34536
|
+
if (options.dryRun !== true && options.yes !== true) {
|
|
34537
|
+
throw new MonitorsUsageError(
|
|
34538
|
+
"monitors batch deploy changes provider monitors asynchronously. Preview with --dry-run, then confirm with --yes."
|
|
34539
|
+
);
|
|
33966
34540
|
}
|
|
33967
|
-
|
|
33968
|
-
|
|
33969
|
-
|
|
34541
|
+
let manifestNdjson;
|
|
34542
|
+
try {
|
|
34543
|
+
manifestNdjson = readFileSync11(resolve14(options.file), "utf8");
|
|
34544
|
+
} catch (error) {
|
|
34545
|
+
throw new MonitorsUsageError(
|
|
34546
|
+
`Could not read monitor batch manifest '${options.file}': ${error instanceof Error ? error.message : String(error)}`
|
|
33970
34547
|
);
|
|
33971
34548
|
}
|
|
33972
|
-
if (
|
|
33973
|
-
|
|
33974
|
-
|
|
34549
|
+
if (!manifestNdjson.trim()) {
|
|
34550
|
+
throw new MonitorsUsageError("Monitor batch manifest is empty.");
|
|
34551
|
+
}
|
|
34552
|
+
const idempotencyKey = monitorBatchIdempotencyKey(
|
|
34553
|
+
"deploy",
|
|
34554
|
+
options.idempotencyKey
|
|
34555
|
+
);
|
|
34556
|
+
const result = await new DeeplineClient().monitors.batch.submit({
|
|
34557
|
+
kind: "deploy",
|
|
34558
|
+
manifestNdjson,
|
|
34559
|
+
dryRun: options.dryRun === true,
|
|
34560
|
+
idempotencyKey
|
|
34561
|
+
});
|
|
34562
|
+
const operation = result.operation;
|
|
34563
|
+
printCommandEnvelope(
|
|
34564
|
+
{ ...result, idempotency_key: idempotencyKey },
|
|
34565
|
+
{
|
|
34566
|
+
json: options.json,
|
|
34567
|
+
text: [
|
|
34568
|
+
`${result.rejoined ? "rejoined" : "submitted"} deploy batch ${operation.runId}`,
|
|
34569
|
+
`state ${operation.state} \xB7 retry key ${idempotencyKey}`,
|
|
34570
|
+
`inspect: deepline monitors batch get ${operation.runId} --json`
|
|
34571
|
+
].join("\n") + "\n"
|
|
34572
|
+
}
|
|
34573
|
+
);
|
|
34574
|
+
}
|
|
34575
|
+
async function handleMonitorBatch(kind, options) {
|
|
34576
|
+
if ((kind === "deactivate" || kind === "reactivate" || kind === "repair") && options.dryRun !== true && options.yes !== true) {
|
|
34577
|
+
throw new MonitorsUsageError(
|
|
34578
|
+
`monitors batch ${kind} changes provider monitors asynchronously. Preview with --dry-run, then confirm with --yes.`
|
|
33975
34579
|
);
|
|
33976
34580
|
}
|
|
33977
|
-
if (
|
|
33978
|
-
|
|
33979
|
-
|
|
34581
|
+
if (kind === "deactivate" && !options.reason?.trim()) {
|
|
34582
|
+
throw new MonitorsUsageError(
|
|
34583
|
+
"monitors batch deactivate requires --reason (for example insufficient_balance or billing_failure)."
|
|
33980
34584
|
);
|
|
33981
34585
|
}
|
|
33982
|
-
|
|
33983
|
-
|
|
34586
|
+
const idempotencyKey = monitorBatchIdempotencyKey(
|
|
34587
|
+
kind,
|
|
34588
|
+
options.idempotencyKey
|
|
34589
|
+
);
|
|
34590
|
+
const result = await new DeeplineClient().monitors.batch.submit({
|
|
34591
|
+
kind,
|
|
34592
|
+
scope: monitorBatchScope(options, kind),
|
|
34593
|
+
dryRun: options.dryRun === true,
|
|
34594
|
+
...options.reason?.trim() ? { deactivationReason: options.reason.trim() } : {},
|
|
34595
|
+
idempotencyKey
|
|
34596
|
+
});
|
|
34597
|
+
const operation = result.operation;
|
|
34598
|
+
const text = [
|
|
34599
|
+
`${result.rejoined ? "rejoined" : "submitted"} ${operation.kind} batch ${operation.runId}`,
|
|
34600
|
+
`state ${operation.state} \xB7 retry key ${idempotencyKey}`,
|
|
34601
|
+
`inspect: deepline monitors batch get ${operation.runId} --json`
|
|
34602
|
+
].join("\n");
|
|
33984
34603
|
printCommandEnvelope(
|
|
33985
|
-
{ ...result,
|
|
33986
|
-
{ json: options.json, text:
|
|
34604
|
+
{ ...result, idempotency_key: idempotencyKey },
|
|
34605
|
+
{ json: options.json, text: `${text}
|
|
34606
|
+
` }
|
|
33987
34607
|
);
|
|
33988
34608
|
}
|
|
33989
|
-
|
|
33990
|
-
|
|
33991
|
-
|
|
33992
|
-
const health = await new DeeplineClient().monitors.health(
|
|
33993
|
-
fleetId ? { fleetId } : {}
|
|
33994
|
-
);
|
|
33995
|
-
printCommandEnvelope(health, {
|
|
33996
|
-
json: options.json,
|
|
33997
|
-
text: monitorHealthText(health)
|
|
34609
|
+
async function handleMonitorBatchGet(operationId, options) {
|
|
34610
|
+
const result = await new DeeplineClient().monitors.batch.get(operationId, {
|
|
34611
|
+
...options.cursor ? { cursor: options.cursor } : {}
|
|
33998
34612
|
});
|
|
34613
|
+
const summary = result.operation.summary ?? {};
|
|
34614
|
+
const text = [
|
|
34615
|
+
`${result.operation.kind} batch ${result.operation.runId}`,
|
|
34616
|
+
`state ${result.operation.state}`,
|
|
34617
|
+
`progress ${JSON.stringify(summary)}`,
|
|
34618
|
+
...result.results ? [
|
|
34619
|
+
`results ${result.results.page.length}${result.results.isDone ? "" : " (more; pass --cursor)"}`
|
|
34620
|
+
] : []
|
|
34621
|
+
].join("\n");
|
|
34622
|
+
printCommandEnvelope(result, { json: options.json, text: `${text}
|
|
34623
|
+
` });
|
|
33999
34624
|
}
|
|
34000
34625
|
function registerMonitorsCommands(program) {
|
|
34001
34626
|
const monitors = program.command("monitors").description("Discover, deploy, and manage Deepline monitors.").showSuggestionAfterError(true).addHelpText(
|
|
@@ -34060,25 +34685,29 @@ Examples:
|
|
|
34060
34685
|
withJsonOption(
|
|
34061
34686
|
monitors.command("repair").description(
|
|
34062
34687
|
"Converge the monitors whose desired and observed states disagree."
|
|
34063
|
-
).option("--fleet <fleet-id>", "Repair one fleet instead of every monitor").option(
|
|
34064
|
-
"--
|
|
34065
|
-
"
|
|
34688
|
+
).option("--fleet <fleet-id>", "Repair one fleet instead of every monitor").option(
|
|
34689
|
+
"--dry-run",
|
|
34690
|
+
"Record the bounded repair plan without provider changes"
|
|
34691
|
+
).option("--yes", "Confirm the asynchronous provider repair").option(
|
|
34692
|
+
"--idempotency-key <key>",
|
|
34693
|
+
"Stable retry key (generated when omitted)"
|
|
34066
34694
|
).addHelpText(
|
|
34067
34695
|
"after",
|
|
34068
34696
|
`
|
|
34069
34697
|
Notes:
|
|
34070
|
-
|
|
34071
|
-
|
|
34072
|
-
|
|
34073
|
-
is
|
|
34698
|
+
This is the short spelling of 'monitors batch repair --target needs-repair'.
|
|
34699
|
+
It handles both direct monitors and Fleet members through one durable
|
|
34700
|
+
service-account worker. An active historical monitor without an upstream id
|
|
34701
|
+
is selected for repair; current Convex writes cannot create that state.
|
|
34074
34702
|
|
|
34075
|
-
|
|
34076
|
-
|
|
34077
|
-
|
|
34703
|
+
It returns a run id immediately. Inspect retained results with
|
|
34704
|
+
'deepline monitors batch get <run-id> --json'. Reuse --idempotency-key after
|
|
34705
|
+
a lost response to rejoin the exact run without another provider request.
|
|
34078
34706
|
|
|
34079
34707
|
Examples:
|
|
34080
34708
|
deepline monitors repair --dry-run
|
|
34081
|
-
deepline monitors repair --
|
|
34709
|
+
deepline monitors repair --yes
|
|
34710
|
+
deepline monitors repair --fleet accounts-eu --yes --idempotency-key repair-eu-2026-09-09
|
|
34082
34711
|
`
|
|
34083
34712
|
)
|
|
34084
34713
|
).action(monitorsAction(handleMonitorsRepair));
|
|
@@ -34101,6 +34730,75 @@ Examples:
|
|
|
34101
34730
|
`
|
|
34102
34731
|
)
|
|
34103
34732
|
).action(monitorsAction(handleMonitorsHealth));
|
|
34733
|
+
const batch = monitors.command("batch").description("Submit or inspect durable bulk monitor operations.");
|
|
34734
|
+
const batchSelectorOptions = (command) => command.option(
|
|
34735
|
+
"--target <target>",
|
|
34736
|
+
"One of: all, all-active, billing-suspended, needs-repair"
|
|
34737
|
+
).option("--fleet <fleet-id>", "Select one Fleet").option("--keys <keys>", "Up to 100 comma-separated monitor keys").option(
|
|
34738
|
+
"--dry-run",
|
|
34739
|
+
"Record the same bounded plan without provider changes"
|
|
34740
|
+
).option(
|
|
34741
|
+
"--idempotency-key <key>",
|
|
34742
|
+
"Stable retry key (generated when omitted)"
|
|
34743
|
+
);
|
|
34744
|
+
withJsonOption(
|
|
34745
|
+
batch.command("deploy").description(
|
|
34746
|
+
"Durably create complete NDJSON monitor definitions through provider bulk create."
|
|
34747
|
+
).requiredOption(
|
|
34748
|
+
"--file <path>",
|
|
34749
|
+
"NDJSON file of complete monitor definitions"
|
|
34750
|
+
).option("--dry-run", "Validate and record the durable deploy plan").option("--yes", "Confirm asynchronous provider creation").option(
|
|
34751
|
+
"--idempotency-key <key>",
|
|
34752
|
+
"Stable retry key (generated when omitted)"
|
|
34753
|
+
)
|
|
34754
|
+
).action(
|
|
34755
|
+
monitorsAction(
|
|
34756
|
+
(options) => handleMonitorBatchDeploy(options)
|
|
34757
|
+
)
|
|
34758
|
+
);
|
|
34759
|
+
withJsonOption(
|
|
34760
|
+
batchSelectorOptions(
|
|
34761
|
+
batch.command("audit").description("Durably audit a selection; defaults to --target all.")
|
|
34762
|
+
)
|
|
34763
|
+
).action(
|
|
34764
|
+
monitorsAction(
|
|
34765
|
+
(options) => handleMonitorBatch("audit", options)
|
|
34766
|
+
)
|
|
34767
|
+
);
|
|
34768
|
+
withJsonOption(
|
|
34769
|
+
batchSelectorOptions(
|
|
34770
|
+
batch.command("repair").description(
|
|
34771
|
+
"Durably re-audit and converge a selection through the existing lifecycle fences."
|
|
34772
|
+
)
|
|
34773
|
+
).option("--yes", "Confirm the asynchronous provider repair")
|
|
34774
|
+
).action(
|
|
34775
|
+
monitorsAction(
|
|
34776
|
+
(options) => handleMonitorBatch("repair", options)
|
|
34777
|
+
)
|
|
34778
|
+
);
|
|
34779
|
+
withJsonOption(
|
|
34780
|
+
batchSelectorOptions(
|
|
34781
|
+
batch.command("deactivate").description(
|
|
34782
|
+
"Durably deactivate a selection through provider batch deletes."
|
|
34783
|
+
)
|
|
34784
|
+
).requiredOption("--reason <reason>", "Declared deactivation reason").option("--yes", "Confirm the asynchronous provider deactivation")
|
|
34785
|
+
).action(
|
|
34786
|
+
monitorsAction(
|
|
34787
|
+
(options) => handleMonitorBatch("deactivate", options)
|
|
34788
|
+
)
|
|
34789
|
+
);
|
|
34790
|
+
withJsonOption(
|
|
34791
|
+
batchSelectorOptions(
|
|
34792
|
+
batch.command("reactivate").description("Durably reactivate a selection after a suspension.")
|
|
34793
|
+
).option("--yes", "Confirm provider reactivation and possible billing")
|
|
34794
|
+
).action(
|
|
34795
|
+
monitorsAction(
|
|
34796
|
+
(options) => handleMonitorBatch("reactivate", options)
|
|
34797
|
+
)
|
|
34798
|
+
);
|
|
34799
|
+
withJsonOption(
|
|
34800
|
+
batch.command("get <operation-id>").description("Read batch progress and one bounded evidence page.").option("--cursor <cursor>", "Read the next retained evidence page")
|
|
34801
|
+
).action(monitorsAction(handleMonitorBatchGet));
|
|
34104
34802
|
withJsonOption(
|
|
34105
34803
|
monitors.command("status").description("Check whether you have access to Deepline monitors.").addHelpText(
|
|
34106
34804
|
"after",
|
|
@@ -34152,8 +34850,9 @@ Examples:
|
|
|
34152
34850
|
"after",
|
|
34153
34851
|
`
|
|
34154
34852
|
Notes:
|
|
34155
|
-
Read-only.
|
|
34156
|
-
|
|
34853
|
+
Read-only. A monitor state is active or inactive; provider disagreement is
|
|
34854
|
+
reported separately by audit/health. The output echoes the state filter that
|
|
34855
|
+
was applied. The response reports
|
|
34157
34856
|
total (the true registry count, not the page size), returned, has_more, and
|
|
34158
34857
|
next_cursor. When has_more is true, page with --cursor <next_cursor> until it
|
|
34159
34858
|
is false \u2014 a "no matching
|
|
@@ -34171,7 +34870,7 @@ Examples:
|
|
|
34171
34870
|
`
|
|
34172
34871
|
).option(
|
|
34173
34872
|
"--status <status>",
|
|
34174
|
-
"Filter by monitor
|
|
34873
|
+
"Filter by monitor state: active (default), inactive, or all"
|
|
34175
34874
|
).option("--limit <n>", "Limit the number of deployed monitors returned").option(
|
|
34176
34875
|
"--cursor <cursor>",
|
|
34177
34876
|
"Page past a truncated result using the next_cursor from a prior list response"
|
|
@@ -34564,7 +35263,7 @@ Example:
|
|
|
34564
35263
|
const deployed = withJsonOption(
|
|
34565
35264
|
monitors.command("deployed", { hidden: true }).description("Alias of `monitors list` (plus get/update/delete aliases).").option(
|
|
34566
35265
|
"--status <status>",
|
|
34567
|
-
"Filter by monitor
|
|
35266
|
+
"Filter by monitor state: active (default), inactive, or all"
|
|
34568
35267
|
).option("--limit <n>", "Limit the number of deployed monitors returned").option(
|
|
34569
35268
|
"--cursor <cursor>",
|
|
34570
35269
|
"Page past a truncated result using the next_cursor from a prior list response"
|
|
@@ -34712,7 +35411,8 @@ function organizationAuthValues(input2) {
|
|
|
34712
35411
|
[HOST_URL_ENV]: input2.baseUrl,
|
|
34713
35412
|
[API_KEY_ENV]: input2.apiKey,
|
|
34714
35413
|
[ACTIVE_ORG_ID_ENV]: input2.orgId,
|
|
34715
|
-
[ACTIVE_ORG_NAME_ENV]: input2.orgName
|
|
35414
|
+
[ACTIVE_ORG_NAME_ENV]: input2.orgName,
|
|
35415
|
+
...featureEnvValues(input2)
|
|
34716
35416
|
};
|
|
34717
35417
|
}
|
|
34718
35418
|
function organizationCommandContext(input2) {
|
|
@@ -34928,6 +35628,7 @@ async function handleOrgSwitch(selection, options) {
|
|
|
34928
35628
|
if (!selection && !options.orgId && authScope === "folder" && provenance.scope === "global" && provenance.project.state === "project") {
|
|
34929
35629
|
const commandContext = resolveCliCommandContext(config);
|
|
34930
35630
|
const activeOrganization = commandContext.active_organization;
|
|
35631
|
+
const pinnedFeatures = storedHostFeatures(config.baseUrl);
|
|
34931
35632
|
const project_env_paths2 = saveProjectDeeplineEnvValues(
|
|
34932
35633
|
{
|
|
34933
35634
|
[HOST_URL_ENV]: config.baseUrl,
|
|
@@ -34935,7 +35636,8 @@ async function handleOrgSwitch(selection, options) {
|
|
|
34935
35636
|
...activeOrganization ? {
|
|
34936
35637
|
[ACTIVE_ORG_ID_ENV]: activeOrganization.org_id,
|
|
34937
35638
|
[ACTIVE_ORG_NAME_ENV]: activeOrganization.org_name ?? ""
|
|
34938
|
-
} : {}
|
|
35639
|
+
} : {},
|
|
35640
|
+
...pinnedFeatures !== void 0 ? { [FEATURES_ENV]: pinnedFeatures } : {}
|
|
34939
35641
|
},
|
|
34940
35642
|
provenance.project.dir
|
|
34941
35643
|
);
|
|
@@ -35015,11 +35717,15 @@ async function handleOrgSwitch(selection, options) {
|
|
|
35015
35717
|
const authTarget = resolveOrgSwitchAuthTarget(authScope, config);
|
|
35016
35718
|
if (target.is_current) {
|
|
35017
35719
|
let project_env_paths2 = [];
|
|
35720
|
+
const features = await http.post("/api/v2/auth/cli/status", {
|
|
35721
|
+
api_key: config.apiKey
|
|
35722
|
+
}).then((status) => status.features).catch(() => void 0);
|
|
35018
35723
|
const authValues2 = organizationAuthValues({
|
|
35019
35724
|
baseUrl: config.baseUrl,
|
|
35020
35725
|
apiKey: config.apiKey,
|
|
35021
35726
|
orgId: target.org_id,
|
|
35022
|
-
orgName: target.name
|
|
35727
|
+
orgName: target.name,
|
|
35728
|
+
features
|
|
35023
35729
|
});
|
|
35024
35730
|
if (authTarget.kind === "folder") {
|
|
35025
35731
|
project_env_paths2 = saveProjectDeeplineEnvValues(authValues2);
|
|
@@ -35086,7 +35792,8 @@ async function handleOrgSwitch(selection, options) {
|
|
|
35086
35792
|
baseUrl: config.baseUrl,
|
|
35087
35793
|
apiKey: switched.api_key,
|
|
35088
35794
|
orgId: switched.org_id,
|
|
35089
|
-
orgName: switched.org_name
|
|
35795
|
+
orgName: switched.org_name,
|
|
35796
|
+
features: switched.features
|
|
35090
35797
|
});
|
|
35091
35798
|
if (authTarget.kind === "folder") {
|
|
35092
35799
|
project_env_paths = saveProjectDeeplineEnvValues(authValues);
|
|
@@ -35158,14 +35865,20 @@ async function handleOrgCreate(name, options) {
|
|
|
35158
35865
|
const identity = await fetchWorkspaceCreationIdentity(http, config.apiKey);
|
|
35159
35866
|
let created;
|
|
35160
35867
|
let workspaceApiKey;
|
|
35868
|
+
let workspaceFeatures;
|
|
35161
35869
|
let pendingIntentPath = null;
|
|
35162
35870
|
if (!identity.orgId) {
|
|
35163
35871
|
const firstWorkspace = await http.post("/api/v2/auth/cli/org-create", {
|
|
35164
35872
|
api_key: config.apiKey,
|
|
35165
35873
|
name: normalizedName
|
|
35166
35874
|
});
|
|
35167
|
-
const {
|
|
35875
|
+
const {
|
|
35876
|
+
api_key: apiKey,
|
|
35877
|
+
features,
|
|
35878
|
+
...publicFirstWorkspace
|
|
35879
|
+
} = firstWorkspace;
|
|
35168
35880
|
workspaceApiKey = apiKey;
|
|
35881
|
+
workspaceFeatures = features;
|
|
35169
35882
|
created = publicFirstWorkspace;
|
|
35170
35883
|
} else {
|
|
35171
35884
|
const pending = loadOrCreatePendingOrgCreate({
|
|
@@ -35186,6 +35899,7 @@ async function handleOrgCreate(name, options) {
|
|
|
35186
35899
|
org_id: workspace.org_id
|
|
35187
35900
|
});
|
|
35188
35901
|
workspaceApiKey = switched.api_key;
|
|
35902
|
+
workspaceFeatures = switched.features;
|
|
35189
35903
|
created = { ...workspace };
|
|
35190
35904
|
pendingIntentPath = pending.path;
|
|
35191
35905
|
}
|
|
@@ -35193,7 +35907,8 @@ async function handleOrgCreate(name, options) {
|
|
|
35193
35907
|
baseUrl: config.baseUrl,
|
|
35194
35908
|
apiKey: workspaceApiKey,
|
|
35195
35909
|
orgId: created.org_id,
|
|
35196
|
-
orgName: created.org_name
|
|
35910
|
+
orgName: created.org_name,
|
|
35911
|
+
features: workspaceFeatures
|
|
35197
35912
|
});
|
|
35198
35913
|
saveHostEnvValues(config.baseUrl, authValues);
|
|
35199
35914
|
if (pendingIntentPath) unlinkSync(pendingIntentPath);
|
|
@@ -35390,6 +36105,7 @@ Examples:
|
|
|
35390
36105
|
}
|
|
35391
36106
|
|
|
35392
36107
|
// src/cli/commands/git.ts
|
|
36108
|
+
var GIT_DEPLOY_FEATURE = "github-deploy";
|
|
35393
36109
|
function renderProject(project) {
|
|
35394
36110
|
const root = project.rootDirectory ? ` (${project.rootDirectory})` : "";
|
|
35395
36111
|
const flags = [
|
|
@@ -35642,7 +36358,7 @@ async function handleDeploymentGet(id, options) {
|
|
|
35642
36358
|
);
|
|
35643
36359
|
}
|
|
35644
36360
|
function registerGitCommands(program) {
|
|
35645
|
-
const git = program.command("git").alias("projects").description(
|
|
36361
|
+
const git = program.command("git", { hidden: !cliFeatureEnabled(GIT_DEPLOY_FEATURE) }).alias("projects").description(
|
|
35646
36362
|
"Git deploys: link repositories to this workspace and deploy plays on push."
|
|
35647
36363
|
).addHelpText(
|
|
35648
36364
|
"after",
|
|
@@ -35963,18 +36679,25 @@ async function handleList2(options) {
|
|
|
35963
36679
|
async function handleCheck(nameInput, options) {
|
|
35964
36680
|
const name = normalizeSecretName(nameInput);
|
|
35965
36681
|
const client2 = new DeeplineClient();
|
|
35966
|
-
const
|
|
36682
|
+
const check = options.play !== void 0 ? await client2.inspectSecret(name, { playName: options.play }) : null;
|
|
36683
|
+
const secret = check ? check.secret : await client2.checkSecret(name);
|
|
36684
|
+
const ok = check ? check.ok : Boolean(secret);
|
|
36685
|
+
const quotedPlay = `'${(options.play ?? "PLAY").replace(/'/g, `'"'"'`)}'`;
|
|
36686
|
+
const scopeHint = check ? secret?.scope === "play" ? check.reason === "disabled" ? `The Play-scoped secret is disabled and no active org fallback is available. Restore it with: deepline secrets set ${name} --scope play --play ${quotedPlay}` : `The active Play-scoped secret takes precedence over the org secret.${ok ? "" : ` Restore it with: deepline secrets set ${name} --scope play --play ${quotedPlay}`}` : `No Play override.${ok ? " The org secret is available." : ` Set or rotate the org secret with: deepline secrets set ${name}`}` : `Metadata only. Verify effective scope and active version with: deepline secrets check ${name} --play <play-name>`;
|
|
35967
36687
|
printCommandEnvelope(
|
|
35968
36688
|
{
|
|
35969
|
-
ok
|
|
36689
|
+
ok,
|
|
35970
36690
|
name,
|
|
35971
36691
|
secret: secret ?? null,
|
|
36692
|
+
check: check ? { playName: check.playName, reason: check.reason } : null,
|
|
36693
|
+
scopeHint,
|
|
35972
36694
|
render: {
|
|
35973
36695
|
sections: [
|
|
35974
36696
|
{
|
|
35975
36697
|
title: "secret check",
|
|
35976
36698
|
lines: [
|
|
35977
|
-
secret ? `${name}: active \u2014 ${renderSecret(secret)}` : `${name}: missing, disabled, or empty
|
|
36699
|
+
check ? `${name}: ${check.reason} for ${check.playName}${secret ? ` (${secret.scope})` : ""}` : secret ? `${name}: active metadata \u2014 ${renderSecret(secret)}` : `${name}: missing, disabled, or empty`,
|
|
36700
|
+
scopeHint
|
|
35978
36701
|
]
|
|
35979
36702
|
}
|
|
35980
36703
|
]
|
|
@@ -35982,7 +36705,7 @@ async function handleCheck(nameInput, options) {
|
|
|
35982
36705
|
},
|
|
35983
36706
|
{ json: options.json }
|
|
35984
36707
|
);
|
|
35985
|
-
if (!
|
|
36708
|
+
if (!ok) process.exitCode = 4;
|
|
35986
36709
|
}
|
|
35987
36710
|
async function handleSet2(nameInput, forbidden, options) {
|
|
35988
36711
|
preventShellHistoryLeak(forbidden);
|
|
@@ -36036,6 +36759,7 @@ Notes:
|
|
|
36036
36759
|
Examples:
|
|
36037
36760
|
deepline secrets list
|
|
36038
36761
|
deepline secrets check HUBSPOT_TOKEN
|
|
36762
|
+
deepline secrets check HUBSPOT_TOKEN --play hubspot-sync
|
|
36039
36763
|
deepline secrets set HUBSPOT_TOKEN
|
|
36040
36764
|
printf %s "$HUBSPOT_TOKEN" | deepline secrets set HUBSPOT_TOKEN --value-stdin
|
|
36041
36765
|
deepline secrets set HUBSPOT_TOKEN --from-env HUBSPOT_TOKEN
|
|
@@ -36045,7 +36769,12 @@ Examples:
|
|
|
36045
36769
|
secrets.command("list").description("List secret metadata only.").option("--json", "Emit JSON output").action(async (options) => {
|
|
36046
36770
|
await handleList2(options);
|
|
36047
36771
|
});
|
|
36048
|
-
secrets.command("check").description(
|
|
36772
|
+
secrets.command("check").description(
|
|
36773
|
+
"Check secret metadata, or effective availability with --play."
|
|
36774
|
+
).argument("<name>", "Secret name").option(
|
|
36775
|
+
"--play <name>",
|
|
36776
|
+
"Validate the effective secret for a bare Play name and active version"
|
|
36777
|
+
).option("--json", "Emit JSON output").action(async (name, options) => {
|
|
36049
36778
|
await handleCheck(name, options);
|
|
36050
36779
|
});
|
|
36051
36780
|
secrets.command("set").description("Set or rotate a secret without exposing its value in argv.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play", "org").option("--play <name>", "Play name for play-scoped secrets").option("--value-stdin", "Read the value from piped stdin").option("--from-env <name>", "Read the value from an environment variable").option("--from-file <path>", "Read the value from a file").action(
|
|
@@ -36438,6 +37167,20 @@ function classifyNetworkFailure(error) {
|
|
|
36438
37167
|
}
|
|
36439
37168
|
return "network_error";
|
|
36440
37169
|
}
|
|
37170
|
+
function classifyNetworkCauseCategory(error) {
|
|
37171
|
+
switch (classifyNetworkFailure(error)) {
|
|
37172
|
+
case "network_dns_resolution_failed":
|
|
37173
|
+
return "dns";
|
|
37174
|
+
case "network_ssl_error":
|
|
37175
|
+
return "tls";
|
|
37176
|
+
case "network_connection_reset":
|
|
37177
|
+
return "reset";
|
|
37178
|
+
case "network_timeout":
|
|
37179
|
+
return "connect_timeout";
|
|
37180
|
+
default:
|
|
37181
|
+
return "unknown";
|
|
37182
|
+
}
|
|
37183
|
+
}
|
|
36441
37184
|
function isNetworkFailure(error) {
|
|
36442
37185
|
if (!(error instanceof Error)) return false;
|
|
36443
37186
|
if (error instanceof DeeplineError && error.statusCode) return false;
|
|
@@ -36607,6 +37350,7 @@ function buildFailureReport(input2) {
|
|
|
36607
37350
|
});
|
|
36608
37351
|
const code = failureCode({ exitCode: input2.exitCode, error: input2.error });
|
|
36609
37352
|
const errorBody = input2.error === void 0 ? `SDK CLI command exited ${input2.exitCode ?? "unknown"}` : errorMessage3(input2.error);
|
|
37353
|
+
const networkCauseCategory = input2.error !== void 0 && isNetworkFailure(input2.error) ? classifyNetworkCauseCategory(input2.error) : null;
|
|
36610
37354
|
return {
|
|
36611
37355
|
command: sanitizeCommand(input2.argv),
|
|
36612
37356
|
subcommand: subcommandFromArgv(input2.argv),
|
|
@@ -36628,7 +37372,8 @@ function buildFailureReport(input2) {
|
|
|
36628
37372
|
failure_code: code,
|
|
36629
37373
|
failure_stage: input2.error === void 0 ? "command_exit" : "cli_main",
|
|
36630
37374
|
duration_ms: durationMs,
|
|
36631
|
-
...input2.exitCode !== null ? { exit_code: input2.exitCode } : {}
|
|
37375
|
+
...input2.exitCode !== null ? { exit_code: input2.exitCode } : {},
|
|
37376
|
+
...networkCauseCategory ? { network_cause_category: networkCauseCategory } : {}
|
|
36632
37377
|
}
|
|
36633
37378
|
};
|
|
36634
37379
|
}
|
|
@@ -38333,6 +39078,9 @@ Examples:
|
|
|
38333
39078
|
});
|
|
38334
39079
|
}
|
|
38335
39080
|
|
|
39081
|
+
// src/cli/commands/settings.ts
|
|
39082
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
39083
|
+
|
|
38336
39084
|
// src/cli/update-preferences.ts
|
|
38337
39085
|
import {
|
|
38338
39086
|
existsSync as existsSync16,
|
|
@@ -38489,6 +39237,8 @@ var SDK_SIDECAR_CRITICAL_PACKAGE_FILES = [
|
|
|
38489
39237
|
"dist/index.d.ts",
|
|
38490
39238
|
"dist/plays/bundle-play-file.mjs",
|
|
38491
39239
|
"dist/bundling-sources/shared_libs/observability/telemetry.ts",
|
|
39240
|
+
"dist/bundling-sources/shared_libs/integration-contracts/bettercontact/execution-policy.ts",
|
|
39241
|
+
"dist/bundling-sources/shared_libs/integration-contracts/theirstack/execution-policy.ts",
|
|
38492
39242
|
"dist/bundling-sources/shared_libs/play-runtime/backend.ts",
|
|
38493
39243
|
"dist/bundling-sources/shared_libs/plays/bundling/index.ts",
|
|
38494
39244
|
"dist/bundling-sources/shared_libs/product-notifications/contract.ts",
|
|
@@ -40045,21 +40795,104 @@ function displaySlackTarget(target) {
|
|
|
40045
40795
|
function collectEvent(value, previous = []) {
|
|
40046
40796
|
return [...previous, value];
|
|
40047
40797
|
}
|
|
40798
|
+
function collectNotificationTarget(value, previous = []) {
|
|
40799
|
+
return [...previous, value];
|
|
40800
|
+
}
|
|
40801
|
+
async function readNotificationConfigurationChange(source, read = (path, encoding) => readFileSync20(path, encoding)) {
|
|
40802
|
+
const label = source === "-" ? "stdin" : source;
|
|
40803
|
+
let text;
|
|
40804
|
+
try {
|
|
40805
|
+
text = await read(source === "-" ? 0 : source, "utf8");
|
|
40806
|
+
} catch (error) {
|
|
40807
|
+
throw new Error(
|
|
40808
|
+
`Could not read notification configuration from ${label}: ${error instanceof Error ? error.message : String(error)}`
|
|
40809
|
+
);
|
|
40810
|
+
}
|
|
40811
|
+
let parsed;
|
|
40812
|
+
try {
|
|
40813
|
+
parsed = JSON.parse(text);
|
|
40814
|
+
} catch (error) {
|
|
40815
|
+
throw new Error(
|
|
40816
|
+
`Notification configuration from ${label} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
40817
|
+
);
|
|
40818
|
+
}
|
|
40819
|
+
if (typeof parsed.expectedWorkspaceVersion !== "number" || !Number.isInteger(parsed.expectedWorkspaceVersion) || !parsed.change || typeof parsed.change !== "object") {
|
|
40820
|
+
throw new Error(
|
|
40821
|
+
`Notification configuration from ${label} must contain an integer expectedWorkspaceVersion and a change object.`
|
|
40822
|
+
);
|
|
40823
|
+
}
|
|
40824
|
+
return {
|
|
40825
|
+
expectedWorkspaceVersion: parsed.expectedWorkspaceVersion,
|
|
40826
|
+
change: parsed.change
|
|
40827
|
+
};
|
|
40828
|
+
}
|
|
40048
40829
|
function registerNotificationCommands(program) {
|
|
40049
|
-
const notifications = program.command("notifications").description("
|
|
40830
|
+
const notifications = program.command("notifications").description("Configure notification groups, destinations, and rules.").addHelpText(
|
|
40050
40831
|
"after",
|
|
40051
40832
|
`
|
|
40052
40833
|
Examples:
|
|
40834
|
+
deepline notifications add oncall --to email:oncall@example.com --to slack:#oncall
|
|
40053
40835
|
deepline notifications events
|
|
40054
40836
|
deepline notifications slack channels --search pipeline
|
|
40055
40837
|
deepline notifications add pipeline-watchdog --to slack:#pipeline-alerts --for play.cron.failed
|
|
40056
40838
|
deepline notifications add owner-alerts --to slack:member:U0123456789 --for play.cron.failed
|
|
40057
40839
|
deepline notifications test pipeline-watchdog
|
|
40058
40840
|
|
|
40059
|
-
|
|
40060
|
-
|
|
40841
|
+
Each named notification is a group. Repeat --to to give it email and Slack
|
|
40842
|
+
destinations. Add rules from the dashboard or notification configuration. The
|
|
40843
|
+
existing one-Slack-target form with --for remains supported and creates the
|
|
40844
|
+
equivalent compatibility group and rules. Slack connections are managed in
|
|
40845
|
+
Dashboard \u2192 Integrations.
|
|
40846
|
+
`
|
|
40847
|
+
);
|
|
40848
|
+
const configuration = notifications.command("configuration").description("Read or atomically update notification groups and rules.").addHelpText(
|
|
40849
|
+
"after",
|
|
40850
|
+
`
|
|
40851
|
+
Examples:
|
|
40852
|
+
deepline notifications configuration get --json
|
|
40853
|
+
deepline notifications configuration apply change.json --dry-run --json
|
|
40854
|
+
jq '{expectedWorkspaceVersion: .configuration.workspaceVersion, change: {kind: "delete_group", groupKey: "oncall"}}' current.json | deepline notifications configuration apply - --json
|
|
40061
40855
|
`
|
|
40062
40856
|
);
|
|
40857
|
+
configuration.command("get").description("Show the effective group-based notification configuration.").option("--json", "Emit JSON output").action(async (options) => {
|
|
40858
|
+
const result = await new DeeplineClient().getNotificationConfiguration();
|
|
40859
|
+
printCommandEnvelope(
|
|
40860
|
+
{
|
|
40861
|
+
...result,
|
|
40862
|
+
render: {
|
|
40863
|
+
sections: [
|
|
40864
|
+
{
|
|
40865
|
+
title: "notification groups",
|
|
40866
|
+
lines: result.configuration.groups.length ? result.configuration.groups.map(
|
|
40867
|
+
(group) => `${group.name}: ${group.enabled ? "active" : "paused"}`
|
|
40868
|
+
) : ["No notification groups are configured."]
|
|
40869
|
+
}
|
|
40870
|
+
]
|
|
40871
|
+
}
|
|
40872
|
+
},
|
|
40873
|
+
{ json: options.json }
|
|
40874
|
+
);
|
|
40875
|
+
});
|
|
40876
|
+
configuration.command("apply").argument(
|
|
40877
|
+
"<file>",
|
|
40878
|
+
"JSON file, or - for stdin, containing expectedWorkspaceVersion and one desired change"
|
|
40879
|
+
).description(
|
|
40880
|
+
"Atomically apply a configuration draft exported by an agent or UI."
|
|
40881
|
+
).option("--dry-run", "Validate and display the file without saving it").option("--json", "Emit JSON output").action(async (file, options) => {
|
|
40882
|
+
const input2 = await readNotificationConfigurationChange(file);
|
|
40883
|
+
if (options.dryRun) {
|
|
40884
|
+
printCommandEnvelope(
|
|
40885
|
+
{ dryRun: true, ...input2 },
|
|
40886
|
+
{ json: options.json }
|
|
40887
|
+
);
|
|
40888
|
+
return;
|
|
40889
|
+
}
|
|
40890
|
+
const result = await new DeeplineClient().changeNotificationConfiguration(
|
|
40891
|
+
input2.expectedWorkspaceVersion,
|
|
40892
|
+
input2.change
|
|
40893
|
+
);
|
|
40894
|
+
printCommandEnvelope(result, { json: options.json });
|
|
40895
|
+
});
|
|
40063
40896
|
notifications.command("events").description("List the Play events available to a notification.").option("--json", "Emit JSON output").action(async (options) => {
|
|
40064
40897
|
const settings = await new DeeplineClient().getNotifications();
|
|
40065
40898
|
printCommandEnvelope(
|
|
@@ -40115,42 +40948,82 @@ chooses the connected Slack channel or member and the events it receives.
|
|
|
40115
40948
|
);
|
|
40116
40949
|
printCommandEnvelope({ notification: rule }, { json: options.json });
|
|
40117
40950
|
});
|
|
40118
|
-
notifications.command("add").argument("<name>", "
|
|
40951
|
+
notifications.command("add").argument("<name>", "Group name, for example oncall").requiredOption(
|
|
40119
40952
|
"--to <target>",
|
|
40120
|
-
"Target
|
|
40953
|
+
"Target; repeat email:name@example.com, slack:#channel, or slack:member:U0123456789",
|
|
40954
|
+
collectNotificationTarget,
|
|
40955
|
+
[]
|
|
40121
40956
|
).option(
|
|
40122
40957
|
"--for <event>",
|
|
40123
|
-
"
|
|
40958
|
+
"Legacy one-Slack-target event ID; repeat for more events",
|
|
40124
40959
|
collectEvent,
|
|
40125
40960
|
[]
|
|
40126
40961
|
).option("--dry-run", "Describe the notification without saving it").option("--json", "Emit JSON output").action(
|
|
40127
40962
|
async (name, options) => {
|
|
40128
|
-
|
|
40129
|
-
|
|
40963
|
+
const result = await new DeeplineClient().createNotificationGroup({
|
|
40964
|
+
name,
|
|
40965
|
+
targets: options.to,
|
|
40966
|
+
legacyEvents: options.for,
|
|
40967
|
+
dryRun: options.dryRun
|
|
40968
|
+
});
|
|
40969
|
+
if (result.mode === "dry_run") {
|
|
40970
|
+
printCommandEnvelope(
|
|
40971
|
+
result.compatibilityMode ? {
|
|
40972
|
+
dryRun: true,
|
|
40973
|
+
name: result.name,
|
|
40974
|
+
target: options.to[0],
|
|
40975
|
+
eventTypes: result.legacyEvents
|
|
40976
|
+
} : {
|
|
40977
|
+
dryRun: true,
|
|
40978
|
+
group: result.name,
|
|
40979
|
+
targets: result.targets,
|
|
40980
|
+
compatibilityMode: false
|
|
40981
|
+
},
|
|
40982
|
+
{ json: options.json }
|
|
40983
|
+
);
|
|
40984
|
+
return;
|
|
40130
40985
|
}
|
|
40131
|
-
|
|
40132
|
-
if (options.dryRun) {
|
|
40986
|
+
if (result.mode === "legacy") {
|
|
40133
40987
|
printCommandEnvelope(
|
|
40134
|
-
{
|
|
40988
|
+
{
|
|
40989
|
+
notification: result.notification,
|
|
40990
|
+
render: {
|
|
40991
|
+
sections: [
|
|
40992
|
+
{
|
|
40993
|
+
title: "notification saved",
|
|
40994
|
+
lines: [name]
|
|
40995
|
+
}
|
|
40996
|
+
],
|
|
40997
|
+
actions: [
|
|
40998
|
+
{
|
|
40999
|
+
label: "Send a test",
|
|
41000
|
+
command: `deepline notifications test ${name}`
|
|
41001
|
+
}
|
|
41002
|
+
]
|
|
41003
|
+
}
|
|
41004
|
+
},
|
|
40135
41005
|
{ json: options.json }
|
|
40136
41006
|
);
|
|
40137
41007
|
return;
|
|
40138
41008
|
}
|
|
40139
|
-
const result = await new DeeplineClient().createNotification({
|
|
40140
|
-
name,
|
|
40141
|
-
provider: "slack",
|
|
40142
|
-
...target,
|
|
40143
|
-
eventTypes: options.for
|
|
40144
|
-
});
|
|
40145
41009
|
printCommandEnvelope(
|
|
40146
41010
|
{
|
|
40147
|
-
|
|
41011
|
+
...result,
|
|
40148
41012
|
render: {
|
|
40149
|
-
sections: [
|
|
41013
|
+
sections: [
|
|
41014
|
+
{
|
|
41015
|
+
title: "notification group saved",
|
|
41016
|
+
lines: [
|
|
41017
|
+
result.group.name,
|
|
41018
|
+
`${result.destinations.length} destination${result.destinations.length === 1 ? "" : "s"}`,
|
|
41019
|
+
"0 rules"
|
|
41020
|
+
]
|
|
41021
|
+
}
|
|
41022
|
+
],
|
|
40150
41023
|
actions: [
|
|
40151
41024
|
{
|
|
40152
|
-
label: "
|
|
40153
|
-
command:
|
|
41025
|
+
label: "View configuration",
|
|
41026
|
+
command: "deepline notifications configuration get"
|
|
40154
41027
|
}
|
|
40155
41028
|
]
|
|
40156
41029
|
}
|
|
@@ -40268,7 +41141,7 @@ import {
|
|
|
40268
41141
|
chmodSync,
|
|
40269
41142
|
existsSync as existsSync19,
|
|
40270
41143
|
mkdtempSync,
|
|
40271
|
-
readFileSync as
|
|
41144
|
+
readFileSync as readFileSync21,
|
|
40272
41145
|
writeFileSync as writeFileSync20
|
|
40273
41146
|
} from "fs";
|
|
40274
41147
|
import { tmpdir as tmpdir5 } from "os";
|
|
@@ -41137,6 +42010,9 @@ async function findPlayForToolId(client2, toolId) {
|
|
|
41137
42010
|
const plays = await client2.searchPlays({ query: requested, compact: true });
|
|
41138
42011
|
return plays.find((play) => playIdentifiers(play).includes(requested)) ?? null;
|
|
41139
42012
|
}
|
|
42013
|
+
function isMissingToolMetadataError(error) {
|
|
42014
|
+
return error instanceof DeeplineError && error.statusCode === 404;
|
|
42015
|
+
}
|
|
41140
42016
|
function playAliasToolErrorMessage(toolId, play) {
|
|
41141
42017
|
const playName = play.reference ?? play.name;
|
|
41142
42018
|
return `${toolId} is a play, not a tool.
|
|
@@ -41418,10 +42294,12 @@ async function getTool(toolId, options = {}) {
|
|
|
41418
42294
|
try {
|
|
41419
42295
|
tool = await client2.getTool(toolId);
|
|
41420
42296
|
} catch (error) {
|
|
41421
|
-
|
|
41422
|
-
|
|
41423
|
-
|
|
41424
|
-
|
|
42297
|
+
if (isMissingToolMetadataError(error)) {
|
|
42298
|
+
const play = await findPlayForToolId(client2, toolId);
|
|
42299
|
+
if (play) {
|
|
42300
|
+
printPlayAliasToolError(toolId, play);
|
|
42301
|
+
return 2;
|
|
42302
|
+
}
|
|
41425
42303
|
}
|
|
41426
42304
|
throw error;
|
|
41427
42305
|
}
|
|
@@ -42409,7 +43287,7 @@ function readJsonArgument(raw, flagName) {
|
|
|
42409
43287
|
throw new Error(`Invalid ${flagName} value: empty @file path.`);
|
|
42410
43288
|
}
|
|
42411
43289
|
try {
|
|
42412
|
-
return
|
|
43290
|
+
return readFileSync21(resolveAtFilePath(filePath), "utf8").replace(
|
|
42413
43291
|
/^\uFEFF/,
|
|
42414
43292
|
""
|
|
42415
43293
|
);
|
|
@@ -42760,19 +43638,18 @@ async function executeTool(args) {
|
|
|
42760
43638
|
try {
|
|
42761
43639
|
metadata = await client2.getTool(parsed.toolId);
|
|
42762
43640
|
} catch (error) {
|
|
42763
|
-
|
|
42764
|
-
|
|
42765
|
-
if (
|
|
42766
|
-
|
|
42767
|
-
|
|
42768
|
-
|
|
42769
|
-
|
|
42770
|
-
|
|
43641
|
+
if (isMissingToolMetadataError(error)) {
|
|
43642
|
+
const play = await findPlayForToolId(client2, parsed.toolId);
|
|
43643
|
+
if (play) {
|
|
43644
|
+
if (argsWantJson(args)) {
|
|
43645
|
+
printJsonError(
|
|
43646
|
+
new Error(playAliasToolErrorMessage(parsed.toolId, play))
|
|
43647
|
+
);
|
|
43648
|
+
} else {
|
|
43649
|
+
printPlayAliasToolError(parsed.toolId, play);
|
|
43650
|
+
}
|
|
43651
|
+
return 2;
|
|
42771
43652
|
}
|
|
42772
|
-
return 2;
|
|
42773
|
-
}
|
|
42774
|
-
if (error instanceof DeeplineError) {
|
|
42775
|
-
throw error;
|
|
42776
43653
|
}
|
|
42777
43654
|
throw error;
|
|
42778
43655
|
}
|