deepline 0.3.55 → 0.3.57
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 +232 -0
- package/dist/bundling-sources/sdk/src/http.ts +1 -1
- package/dist/bundling-sources/sdk/src/index.ts +29 -0
- package/dist/bundling-sources/sdk/src/monitor-fleet-contract.ts +556 -0
- package/dist/bundling-sources/sdk/src/monitor-fleets.ts +31 -0
- package/dist/bundling-sources/sdk/src/play.ts +2 -8
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/monitor-fleet-limits.ts +14 -0
- package/dist/bundling-sources/shared_libs/monitors/org-monitor-limits.ts +102 -0
- package/dist/bundling-sources/shared_libs/monitors/validation.ts +244 -0
- package/dist/bundling-sources/shared_libs/play-runtime/coordinator-headers.ts +1 -1
- package/dist/cli/index.js +1688 -356
- package/dist/cli/index.mjs +1624 -292
- package/dist/index.d.mts +220 -9
- package/dist/index.d.ts +220 -9
- package/dist/index.js +474 -14
- package/dist/index.mjs +464 -14
- package/dist/install-integrity.json +5 -0
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -1060,7 +1060,7 @@ var SDK_RELEASE = {
|
|
|
1060
1060
|
// available at toolResponse.rawV2 while toolResponse.raw and all declared
|
|
1061
1061
|
// getters keep their established compatibility behavior.
|
|
1062
1062
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1063
|
-
version: "0.3.
|
|
1063
|
+
version: "0.3.57",
|
|
1064
1064
|
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.",
|
|
1065
1065
|
packageCapabilities: {
|
|
1066
1066
|
updatePreferences: 1
|
|
@@ -2197,7 +2197,7 @@ function decodeSseFrame(frame) {
|
|
|
2197
2197
|
return parsed;
|
|
2198
2198
|
}
|
|
2199
2199
|
function sleep(ms) {
|
|
2200
|
-
return new Promise((
|
|
2200
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
2201
2201
|
}
|
|
2202
2202
|
function withCoworkNetworkHint(message) {
|
|
2203
2203
|
if (!isCoworkLikeSandbox2() || message.includes(COWORK_NETWORK_HINT)) {
|
|
@@ -3100,9 +3100,9 @@ function nonEmptyString(value) {
|
|
|
3100
3100
|
}
|
|
3101
3101
|
function normalizeDatasetBornFrom(value) {
|
|
3102
3102
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
3103
|
-
const
|
|
3104
|
-
const table = nonEmptyString(
|
|
3105
|
-
const rowCountIn = finiteNonNegativeInteger2(
|
|
3103
|
+
const record2 = value;
|
|
3104
|
+
const table = nonEmptyString(record2.table);
|
|
3105
|
+
const rowCountIn = finiteNonNegativeInteger2(record2.rowCountIn);
|
|
3106
3106
|
if (!table || rowCountIn === null) return null;
|
|
3107
3107
|
return { table, rowCountIn };
|
|
3108
3108
|
}
|
|
@@ -3962,14 +3962,14 @@ async function* observeRunEvents(options) {
|
|
|
3962
3962
|
try {
|
|
3963
3963
|
for (; ; ) {
|
|
3964
3964
|
if (queue.length === 0) {
|
|
3965
|
-
const waitForItem = new Promise((
|
|
3966
|
-
wake =
|
|
3965
|
+
const waitForItem = new Promise((resolve21) => {
|
|
3966
|
+
wake = resolve21;
|
|
3967
3967
|
});
|
|
3968
3968
|
if (!sawFirstSnapshot) {
|
|
3969
3969
|
const timedOut = await Promise.race([
|
|
3970
3970
|
waitForItem.then(() => false),
|
|
3971
3971
|
new Promise(
|
|
3972
|
-
(
|
|
3972
|
+
(resolve21) => setTimeout(() => resolve21(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
|
|
3973
3973
|
)
|
|
3974
3974
|
]);
|
|
3975
3975
|
if (timedOut && queue.length === 0) {
|
|
@@ -4162,21 +4162,21 @@ function normalizePlayRuntimeNamespace(value) {
|
|
|
4162
4162
|
}
|
|
4163
4163
|
function normalizePlayRuntimeSelection(value) {
|
|
4164
4164
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
4165
|
-
const
|
|
4166
|
-
if (Object.keys(
|
|
4165
|
+
const record2 = value;
|
|
4166
|
+
if (Object.keys(record2).some(
|
|
4167
4167
|
(key) => key !== "environment" && key !== "namespace" && key !== "backend"
|
|
4168
|
-
) ||
|
|
4168
|
+
) || record2.environment !== "preview") {
|
|
4169
4169
|
return null;
|
|
4170
4170
|
}
|
|
4171
|
-
const namespace = normalizePlayRuntimeNamespace(
|
|
4171
|
+
const namespace = normalizePlayRuntimeNamespace(record2.namespace);
|
|
4172
4172
|
if (!namespace) return null;
|
|
4173
|
-
if (
|
|
4173
|
+
if (record2.backend === void 0) {
|
|
4174
4174
|
return { environment: "preview", namespace };
|
|
4175
4175
|
}
|
|
4176
|
-
if (
|
|
4176
|
+
if (record2.backend !== PLAY_RUNTIME_BACKENDS.daytona && record2.backend !== PLAY_RUNTIME_BACKENDS.modal) {
|
|
4177
4177
|
return null;
|
|
4178
4178
|
}
|
|
4179
|
-
return { environment: "preview", namespace, backend:
|
|
4179
|
+
return { environment: "preview", namespace, backend: record2.backend };
|
|
4180
4180
|
}
|
|
4181
4181
|
function normalizePlayRuntimeEnvironment(value) {
|
|
4182
4182
|
return typeof value === "string" && PLAY_RUNTIME_ENVIRONMENTS.includes(value) ? value : null;
|
|
@@ -4328,7 +4328,7 @@ function parseEnvTestPolicyOverrides() {
|
|
|
4328
4328
|
return normalizeTestPolicyOverrides(parsed, "DEEPLINE_TEST_POLICY_OVERRIDES");
|
|
4329
4329
|
}
|
|
4330
4330
|
function sleep2(ms) {
|
|
4331
|
-
return new Promise((
|
|
4331
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
4332
4332
|
}
|
|
4333
4333
|
function isTransientCompileManifestError(error) {
|
|
4334
4334
|
if (error instanceof DeeplineError && typeof error.statusCode === "number") {
|
|
@@ -4760,7 +4760,14 @@ var DeeplineClient = class {
|
|
|
4760
4760
|
dependents: (key) => this.getMonitorDependents(key),
|
|
4761
4761
|
update: (key, patch) => this.updateMonitor(key, patch),
|
|
4762
4762
|
delete: (key, options2) => this.deleteMonitor(key, options2),
|
|
4763
|
-
reactivate: (key, options2) => this.reactivateMonitor(key, options2)
|
|
4763
|
+
reactivate: (key, options2) => this.reactivateMonitor(key, options2),
|
|
4764
|
+
fleets: {
|
|
4765
|
+
sync: (definitionOrId, options2) => this.syncMonitorFleet(definitionOrId, options2),
|
|
4766
|
+
get: (fleetId, options2) => fleetId === void 0 ? this.listMonitorFleets() : this.getMonitorFleet(fleetId, options2),
|
|
4767
|
+
list: () => this.listMonitorFleets(),
|
|
4768
|
+
deactivate: (fleetId, options2) => this.deactivateMonitorFleet(fleetId, options2),
|
|
4769
|
+
waitForConvergence: (fleetId, options2) => this.waitForMonitorFleetConvergence(fleetId, options2)
|
|
4770
|
+
}
|
|
4764
4771
|
};
|
|
4765
4772
|
}
|
|
4766
4773
|
/** The resolved base URL this client is targeting (e.g. `"http://localhost:3000"`). */
|
|
@@ -7068,6 +7075,104 @@ var DeeplineClient = class {
|
|
|
7068
7075
|
{ method: "POST", body: {} }
|
|
7069
7076
|
);
|
|
7070
7077
|
}
|
|
7078
|
+
// ——————————————————————————————————————————————————————————
|
|
7079
|
+
// Monitor Fleets
|
|
7080
|
+
// ——————————————————————————————————————————————————————————
|
|
7081
|
+
monitorFleetIdempotencyKey(operation) {
|
|
7082
|
+
const uuid = globalThis.crypto?.randomUUID?.();
|
|
7083
|
+
return `monitor-fleet-${operation}-${uuid ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`}`;
|
|
7084
|
+
}
|
|
7085
|
+
monitorFleetHeaders(operation, idempotencyKey) {
|
|
7086
|
+
return {
|
|
7087
|
+
"Idempotency-Key": idempotencyKey?.trim() || this.monitorFleetIdempotencyKey(operation)
|
|
7088
|
+
};
|
|
7089
|
+
}
|
|
7090
|
+
monitorFleetPath(fleetId) {
|
|
7091
|
+
return `/api/v2/monitors/fleets/${encodeURIComponent(fleetId)}`;
|
|
7092
|
+
}
|
|
7093
|
+
/**
|
|
7094
|
+
* Create, update, or re-plan one fleet.
|
|
7095
|
+
*
|
|
7096
|
+
* The fleet id is always the resource path, so the same definition PUT twice
|
|
7097
|
+
* is the same operation and the server can answer `replayed: true` instead of
|
|
7098
|
+
* building a second set of monitors. Re-planning an existing fleet from its
|
|
7099
|
+
* stored definition sends an EMPTY body: there is no second definition to
|
|
7100
|
+
* send, and an empty body cannot be mistaken for "replace the definition with
|
|
7101
|
+
* nothing".
|
|
7102
|
+
*/
|
|
7103
|
+
async syncMonitorFleet(definitionOrId, options) {
|
|
7104
|
+
const fleetId = typeof definitionOrId === "string" ? definitionOrId : definitionOrId.id;
|
|
7105
|
+
const body = {
|
|
7106
|
+
...typeof definitionOrId === "string" ? {} : { definition: definitionOrId },
|
|
7107
|
+
...options?.dryRun ? { dry_run: true } : {},
|
|
7108
|
+
...options?.expectedGeneration !== void 0 ? { expected_generation: options.expectedGeneration } : {}
|
|
7109
|
+
};
|
|
7110
|
+
return this.http.request(
|
|
7111
|
+
this.monitorFleetPath(fleetId),
|
|
7112
|
+
{
|
|
7113
|
+
method: "PUT",
|
|
7114
|
+
body,
|
|
7115
|
+
headers: this.monitorFleetHeaders("sync", options?.idempotencyKey),
|
|
7116
|
+
maxRetries: 0,
|
|
7117
|
+
exactUrlOnly: true
|
|
7118
|
+
}
|
|
7119
|
+
);
|
|
7120
|
+
}
|
|
7121
|
+
async listMonitorFleets() {
|
|
7122
|
+
return this.http.request("/api/v2/monitors/fleets", {
|
|
7123
|
+
method: "GET"
|
|
7124
|
+
});
|
|
7125
|
+
}
|
|
7126
|
+
async getMonitorFleet(fleetId, options) {
|
|
7127
|
+
const params = new URLSearchParams();
|
|
7128
|
+
if (options?.drift) params.set("drift", "1");
|
|
7129
|
+
if (options?.limit !== void 0)
|
|
7130
|
+
params.set("limit", String(options.limit));
|
|
7131
|
+
const query = params.toString();
|
|
7132
|
+
return this.http.request(
|
|
7133
|
+
`${this.monitorFleetPath(fleetId)}${query ? `?${query}` : ""}`,
|
|
7134
|
+
{ method: "GET" }
|
|
7135
|
+
);
|
|
7136
|
+
}
|
|
7137
|
+
async deactivateMonitorFleet(fleetId, options) {
|
|
7138
|
+
return this.http.request(
|
|
7139
|
+
this.monitorFleetPath(fleetId),
|
|
7140
|
+
{
|
|
7141
|
+
method: "DELETE",
|
|
7142
|
+
body: options?.dryRun ? { dry_run: true } : {},
|
|
7143
|
+
headers: this.monitorFleetHeaders(
|
|
7144
|
+
"deactivate",
|
|
7145
|
+
options?.idempotencyKey
|
|
7146
|
+
),
|
|
7147
|
+
maxRetries: 0,
|
|
7148
|
+
exactUrlOnly: true
|
|
7149
|
+
}
|
|
7150
|
+
);
|
|
7151
|
+
}
|
|
7152
|
+
/**
|
|
7153
|
+
* Poll one fleet until the server reports a terminal status.
|
|
7154
|
+
*
|
|
7155
|
+
* Convergence is the server's verdict, read from `status`. The timeout is not
|
|
7156
|
+
* a failure and does not throw: a fleet still `converging` after ten minutes
|
|
7157
|
+
* is healthy and slow, not broken, so the caller gets the last snapshot and
|
|
7158
|
+
* decides what that means. Throwing here would have made "still working" look
|
|
7159
|
+
* identical to "the request failed".
|
|
7160
|
+
*/
|
|
7161
|
+
async waitForMonitorFleetConvergence(fleetId, options) {
|
|
7162
|
+
const timeoutMs = Math.max(1, options?.timeoutMs ?? 10 * 6e4);
|
|
7163
|
+
const pollIntervalMs = Math.max(1, options?.pollIntervalMs ?? 2e3);
|
|
7164
|
+
const terminal = options?.until === "deactivated" ? /* @__PURE__ */ new Set(["deactivated", "degraded"]) : /* @__PURE__ */ new Set(["converged", "degraded", "deactivated"]);
|
|
7165
|
+
const startedAt = Date.now();
|
|
7166
|
+
let latest = await this.getMonitorFleet(fleetId);
|
|
7167
|
+
while (true) {
|
|
7168
|
+
options?.onProgress?.(latest);
|
|
7169
|
+
const status = typeof latest.status === "string" ? latest.status : void 0;
|
|
7170
|
+
if (status && terminal.has(status)) return latest;
|
|
7171
|
+
if (Date.now() - startedAt >= timeoutMs) return latest;
|
|
7172
|
+
await sleep2(pollIntervalMs);
|
|
7173
|
+
latest = await this.getMonitorFleet(fleetId);
|
|
7174
|
+
}
|
|
7175
|
+
}
|
|
7071
7176
|
/**
|
|
7072
7177
|
* Check API connectivity and server health.
|
|
7073
7178
|
*
|
|
@@ -7746,30 +7851,30 @@ function flattenObjectColumns(row, options = {}) {
|
|
|
7746
7851
|
continue;
|
|
7747
7852
|
}
|
|
7748
7853
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
7749
|
-
const
|
|
7854
|
+
const record2 = value;
|
|
7750
7855
|
if (options.objectColumns === "json") {
|
|
7751
|
-
flattened[key] = csvSafeJsonString(
|
|
7856
|
+
flattened[key] = csvSafeJsonString(record2);
|
|
7752
7857
|
continue;
|
|
7753
7858
|
}
|
|
7754
|
-
const hasMatchedEnvelope = Object.prototype.hasOwnProperty.call(
|
|
7859
|
+
const hasMatchedEnvelope = Object.prototype.hasOwnProperty.call(record2, "matched_result") || Object.prototype.hasOwnProperty.call(record2, "matchedResult");
|
|
7755
7860
|
if (hasMatchedEnvelope) {
|
|
7756
|
-
flattened[key] = csvSafeJsonString(
|
|
7861
|
+
flattened[key] = csvSafeJsonString(record2);
|
|
7757
7862
|
continue;
|
|
7758
7863
|
}
|
|
7759
7864
|
if (parsedFromString && shouldPreserveJsonStringColumn(options.preserveJsonStringColumns, key)) {
|
|
7760
7865
|
flattened[key] = rawValue;
|
|
7761
7866
|
continue;
|
|
7762
7867
|
} else {
|
|
7763
|
-
const failureMessage = failureMessageFromRecord(
|
|
7868
|
+
const failureMessage = failureMessageFromRecord(record2);
|
|
7764
7869
|
if (failureMessage) {
|
|
7765
7870
|
flattened[key] = failureMessage;
|
|
7766
7871
|
continue;
|
|
7767
|
-
} else if (Object.prototype.hasOwnProperty.call(
|
|
7768
|
-
flattened[key] = csvSafeJsonString(
|
|
7872
|
+
} else if (Object.prototype.hasOwnProperty.call(record2, "result")) {
|
|
7873
|
+
flattened[key] = csvSafeJsonString(record2);
|
|
7769
7874
|
continue;
|
|
7770
7875
|
}
|
|
7771
7876
|
}
|
|
7772
|
-
for (const [nestedKey, nestedValue] of Object.entries(
|
|
7877
|
+
for (const [nestedKey, nestedValue] of Object.entries(record2)) {
|
|
7773
7878
|
flattened[`${key}.${nestedKey}`] = nestedValue && typeof nestedValue === "object" ? csvSafeJsonString(nestedValue) : nestedValue;
|
|
7774
7879
|
}
|
|
7775
7880
|
continue;
|
|
@@ -8158,7 +8263,7 @@ function buildCandidateUrls2(url) {
|
|
|
8158
8263
|
}
|
|
8159
8264
|
}
|
|
8160
8265
|
function sleep4(ms) {
|
|
8161
|
-
return new Promise((
|
|
8266
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
8162
8267
|
}
|
|
8163
8268
|
function printDeeplineLogo() {
|
|
8164
8269
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
@@ -10261,9 +10366,9 @@ function canonicalDatasetJsonValue(value, ancestors) {
|
|
|
10261
10366
|
}
|
|
10262
10367
|
if (ancestors.has(value)) return value;
|
|
10263
10368
|
ancestors.add(value);
|
|
10264
|
-
const
|
|
10369
|
+
const record2 = value;
|
|
10265
10370
|
const normalized = Object.fromEntries(
|
|
10266
|
-
Object.keys(
|
|
10371
|
+
Object.keys(record2).sort((left, right) => left.localeCompare(right)).map((key) => [key, canonicalDatasetJsonValue(record2[key], ancestors)])
|
|
10267
10372
|
);
|
|
10268
10373
|
ancestors.delete(value);
|
|
10269
10374
|
return normalized;
|
|
@@ -11430,16 +11535,16 @@ function collectErrorText(value) {
|
|
|
11430
11535
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
11431
11536
|
return errorMessage(value);
|
|
11432
11537
|
}
|
|
11433
|
-
const
|
|
11538
|
+
const record2 = value;
|
|
11434
11539
|
return [
|
|
11435
11540
|
errorMessage(value),
|
|
11436
|
-
typeof
|
|
11437
|
-
typeof
|
|
11438
|
-
typeof
|
|
11439
|
-
typeof
|
|
11440
|
-
typeof
|
|
11441
|
-
|
|
11442
|
-
|
|
11541
|
+
typeof record2.error === "string" ? record2.error : "",
|
|
11542
|
+
typeof record2.message === "string" ? record2.message : "",
|
|
11543
|
+
typeof record2.detail === "string" ? record2.detail : "",
|
|
11544
|
+
typeof record2.hint === "string" ? record2.hint : "",
|
|
11545
|
+
typeof record2.code === "string" ? record2.code : "",
|
|
11546
|
+
record2.response ? collectErrorText(record2.response) : "",
|
|
11547
|
+
record2.details ? collectErrorText(record2.details) : ""
|
|
11443
11548
|
].filter(Boolean).join("\n");
|
|
11444
11549
|
}
|
|
11445
11550
|
function formatDbQueryError(sql, error) {
|
|
@@ -12491,8 +12596,8 @@ function getterNamesFromTool(tool, kind) {
|
|
|
12491
12596
|
return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
|
|
12492
12597
|
}
|
|
12493
12598
|
function targetGettersFromTool(tool) {
|
|
12494
|
-
const
|
|
12495
|
-
const raw =
|
|
12599
|
+
const record2 = isRecord9(tool) ? tool : {};
|
|
12600
|
+
const raw = record2.targetGetters ?? record2.target_getters;
|
|
12496
12601
|
if (!isRecord9(raw)) return {};
|
|
12497
12602
|
const entries = [];
|
|
12498
12603
|
for (const [target, value] of Object.entries(raw)) {
|
|
@@ -15370,11 +15475,11 @@ function staticStringFromExpression(node, context, seen = /* @__PURE__ */ new Se
|
|
|
15370
15475
|
if (!value?.trim()) return null;
|
|
15371
15476
|
return trimResult ? value.trim() : value;
|
|
15372
15477
|
}
|
|
15373
|
-
const
|
|
15374
|
-
if (!
|
|
15375
|
-
seen.add(
|
|
15478
|
+
const identifier2 = getIdentifierName2(expression);
|
|
15479
|
+
if (!identifier2 || seen.has(identifier2)) return null;
|
|
15480
|
+
seen.add(identifier2);
|
|
15376
15481
|
return staticStringFromExpression(
|
|
15377
|
-
context.declarations.get(
|
|
15482
|
+
context.declarations.get(identifier2),
|
|
15378
15483
|
context,
|
|
15379
15484
|
seen,
|
|
15380
15485
|
trimResult
|
|
@@ -15398,11 +15503,11 @@ function objectExpressionFromNode(node, context, seen = /* @__PURE__ */ new Set(
|
|
|
15398
15503
|
const expression = unwrapStaticExpression2(node);
|
|
15399
15504
|
if (!expression) return null;
|
|
15400
15505
|
if (expression.type === "ObjectExpression") return expression;
|
|
15401
|
-
const
|
|
15402
|
-
if (!
|
|
15403
|
-
seen.add(
|
|
15506
|
+
const identifier2 = getIdentifierName2(expression);
|
|
15507
|
+
if (!identifier2 || seen.has(identifier2)) return null;
|
|
15508
|
+
seen.add(identifier2);
|
|
15404
15509
|
return objectExpressionFromNode(
|
|
15405
|
-
context.declarations.get(
|
|
15510
|
+
context.declarations.get(identifier2),
|
|
15406
15511
|
context,
|
|
15407
15512
|
seen
|
|
15408
15513
|
);
|
|
@@ -15470,11 +15575,11 @@ function staticNumberFromExpression(node, context, seen = /* @__PURE__ */ new Se
|
|
|
15470
15575
|
if (expression.type === "Literal" && typeof expression.value === "number") {
|
|
15471
15576
|
return expression.value;
|
|
15472
15577
|
}
|
|
15473
|
-
const
|
|
15474
|
-
if (!
|
|
15475
|
-
seen.add(
|
|
15578
|
+
const identifier2 = getIdentifierName2(expression);
|
|
15579
|
+
if (!identifier2 || seen.has(identifier2)) return null;
|
|
15580
|
+
seen.add(identifier2);
|
|
15476
15581
|
return staticNumberFromExpression(
|
|
15477
|
-
context.declarations.get(
|
|
15582
|
+
context.declarations.get(identifier2),
|
|
15478
15583
|
context,
|
|
15479
15584
|
seen
|
|
15480
15585
|
);
|
|
@@ -16546,13 +16651,13 @@ function validateFixtureBehavior(value) {
|
|
|
16546
16651
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
16547
16652
|
return { ok: false, error: "fixtureBehavior must be a JSON object." };
|
|
16548
16653
|
}
|
|
16549
|
-
const
|
|
16550
|
-
const supportedKeys =
|
|
16654
|
+
const record2 = value;
|
|
16655
|
+
const supportedKeys = record2.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION || record2.version === FIXTURE_BEHAVIOR_REPLAY_VERSION ? /* @__PURE__ */ new Set([
|
|
16551
16656
|
"version",
|
|
16552
16657
|
"responseSamples",
|
|
16553
|
-
...
|
|
16658
|
+
...record2.version === FIXTURE_BEHAVIOR_REPLAY_VERSION ? ["replayBundle"] : []
|
|
16554
16659
|
]) : /* @__PURE__ */ new Set(["version", "responseDelaySamplesMs"]);
|
|
16555
|
-
const unknownKeys = Object.keys(
|
|
16660
|
+
const unknownKeys = Object.keys(record2).filter(
|
|
16556
16661
|
(key) => !supportedKeys.has(key)
|
|
16557
16662
|
);
|
|
16558
16663
|
if (unknownKeys.length > 0) {
|
|
@@ -16561,22 +16666,22 @@ function validateFixtureBehavior(value) {
|
|
|
16561
16666
|
error: `Unsupported fixtureBehavior field "${unknownKeys[0]}".`
|
|
16562
16667
|
};
|
|
16563
16668
|
}
|
|
16564
|
-
if (
|
|
16669
|
+
if (record2.version !== FIXTURE_BEHAVIOR_VERSION && record2.version !== FIXTURE_BEHAVIOR_RESPONSE_VERSION && record2.version !== FIXTURE_BEHAVIOR_REPLAY_VERSION) {
|
|
16565
16670
|
return {
|
|
16566
16671
|
ok: false,
|
|
16567
16672
|
error: `fixtureBehavior.version must be ${FIXTURE_BEHAVIOR_VERSION} or ${FIXTURE_BEHAVIOR_RESPONSE_VERSION}, or ${FIXTURE_BEHAVIOR_REPLAY_VERSION}.`
|
|
16568
16673
|
};
|
|
16569
16674
|
}
|
|
16570
|
-
if (
|
|
16571
|
-
if (!Array.isArray(
|
|
16675
|
+
if (record2.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION || record2.version === FIXTURE_BEHAVIOR_REPLAY_VERSION) {
|
|
16676
|
+
if (!Array.isArray(record2.responseSamples) || record2.responseSamples.length === 0 || record2.responseSamples.length > MAX_FIXTURE_RESPONSE_DELAY_SAMPLES) {
|
|
16572
16677
|
return {
|
|
16573
16678
|
ok: false,
|
|
16574
16679
|
error: `fixtureBehavior.responseSamples must contain between 1 and ${MAX_FIXTURE_RESPONSE_DELAY_SAMPLES} values.`
|
|
16575
16680
|
};
|
|
16576
16681
|
}
|
|
16577
16682
|
const samples2 = [];
|
|
16578
|
-
for (let index = 0; index <
|
|
16579
|
-
const value2 =
|
|
16683
|
+
for (let index = 0; index < record2.responseSamples.length; index += 1) {
|
|
16684
|
+
const value2 = record2.responseSamples[index];
|
|
16580
16685
|
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
|
|
16581
16686
|
return {
|
|
16582
16687
|
ok: false,
|
|
@@ -16675,14 +16780,14 @@ function validateFixtureBehavior(value) {
|
|
|
16675
16780
|
});
|
|
16676
16781
|
}
|
|
16677
16782
|
let replayBundle;
|
|
16678
|
-
if (
|
|
16679
|
-
if (!
|
|
16783
|
+
if (record2.version === FIXTURE_BEHAVIOR_REPLAY_VERSION) {
|
|
16784
|
+
if (!record2.replayBundle || typeof record2.replayBundle !== "object" || Array.isArray(record2.replayBundle)) {
|
|
16680
16785
|
return {
|
|
16681
16786
|
ok: false,
|
|
16682
16787
|
error: "fixtureBehavior.replayBundle must be an object."
|
|
16683
16788
|
};
|
|
16684
16789
|
}
|
|
16685
|
-
const replay =
|
|
16790
|
+
const replay = record2.replayBundle;
|
|
16686
16791
|
const replayUnknownKeys = Object.keys(replay).filter(
|
|
16687
16792
|
(key) => key !== "bundleId" && key !== "manifestSha256" && key !== "syntheticFallbackToolIds"
|
|
16688
16793
|
);
|
|
@@ -16730,7 +16835,7 @@ function validateFixtureBehavior(value) {
|
|
|
16730
16835
|
...syntheticFallbackToolIds ? { syntheticFallbackToolIds } : {}
|
|
16731
16836
|
};
|
|
16732
16837
|
}
|
|
16733
|
-
if (
|
|
16838
|
+
if (record2.version === FIXTURE_BEHAVIOR_REPLAY_VERSION) {
|
|
16734
16839
|
return {
|
|
16735
16840
|
ok: true,
|
|
16736
16841
|
behavior: {
|
|
@@ -16748,15 +16853,15 @@ function validateFixtureBehavior(value) {
|
|
|
16748
16853
|
}
|
|
16749
16854
|
};
|
|
16750
16855
|
}
|
|
16751
|
-
if (!Array.isArray(
|
|
16856
|
+
if (!Array.isArray(record2.responseDelaySamplesMs) || record2.responseDelaySamplesMs.length === 0 || record2.responseDelaySamplesMs.length > MAX_FIXTURE_RESPONSE_DELAY_SAMPLES) {
|
|
16752
16857
|
return {
|
|
16753
16858
|
ok: false,
|
|
16754
16859
|
error: `fixtureBehavior.responseDelaySamplesMs must contain between 1 and ${MAX_FIXTURE_RESPONSE_DELAY_SAMPLES} values.`
|
|
16755
16860
|
};
|
|
16756
16861
|
}
|
|
16757
16862
|
const samples = [];
|
|
16758
|
-
for (let index = 0; index <
|
|
16759
|
-
const value2 =
|
|
16863
|
+
for (let index = 0; index < record2.responseDelaySamplesMs.length; index += 1) {
|
|
16864
|
+
const value2 = record2.responseDelaySamplesMs[index];
|
|
16760
16865
|
if (typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < 0 || value2 > MAX_FIXTURE_RESPONSE_DELAY_MS) {
|
|
16761
16866
|
return {
|
|
16762
16867
|
ok: false,
|
|
@@ -16965,7 +17070,7 @@ function traceCliSync(phase, fields, run) {
|
|
|
16965
17070
|
}
|
|
16966
17071
|
}
|
|
16967
17072
|
function sleep5(ms) {
|
|
16968
|
-
return new Promise((
|
|
17073
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
16969
17074
|
}
|
|
16970
17075
|
function parseReferencedPlayTarget2(target) {
|
|
16971
17076
|
const trimmed = target.trim();
|
|
@@ -17498,8 +17603,8 @@ function looksLikeStagedFileRef(value) {
|
|
|
17498
17603
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
17499
17604
|
return false;
|
|
17500
17605
|
}
|
|
17501
|
-
const
|
|
17502
|
-
return typeof
|
|
17606
|
+
const record2 = value;
|
|
17607
|
+
return typeof record2.contentHash === "string" || typeof record2.contentBase64 === "string" || typeof record2.logicalPath === "string" && typeof record2.bytes === "number";
|
|
17503
17608
|
}
|
|
17504
17609
|
var CSV_DATA_INPUT_KEY = "csv";
|
|
17505
17610
|
function collectLocalFileInputRefs(value, inputPath, key, out) {
|
|
@@ -18000,8 +18105,8 @@ function readLiveRunField(event, field) {
|
|
|
18000
18105
|
const records = [payload, payload.progress, run, run?.progress].filter(
|
|
18001
18106
|
(value) => Boolean(value && typeof value === "object" && !Array.isArray(value))
|
|
18002
18107
|
);
|
|
18003
|
-
for (const
|
|
18004
|
-
if (
|
|
18108
|
+
for (const record2 of records) {
|
|
18109
|
+
if (record2[field] !== void 0) return record2[field];
|
|
18005
18110
|
}
|
|
18006
18111
|
return void 0;
|
|
18007
18112
|
}
|
|
@@ -18303,8 +18408,8 @@ function getProgressLinesFromLiveEvent(event) {
|
|
|
18303
18408
|
if (!state || typeof state !== "object" || Array.isArray(state)) {
|
|
18304
18409
|
continue;
|
|
18305
18410
|
}
|
|
18306
|
-
const
|
|
18307
|
-
const progress =
|
|
18411
|
+
const record2 = state;
|
|
18412
|
+
const progress = record2.progress && typeof record2.progress === "object" && !Array.isArray(record2.progress) ? record2.progress : null;
|
|
18308
18413
|
if (!progress) {
|
|
18309
18414
|
continue;
|
|
18310
18415
|
}
|
|
@@ -18321,7 +18426,7 @@ function getProgressLinesFromLiveEvent(event) {
|
|
|
18321
18426
|
completed: progress.completed
|
|
18322
18427
|
});
|
|
18323
18428
|
lines.push(
|
|
18324
|
-
`progress ${formatProgressLabel(
|
|
18429
|
+
`progress ${formatProgressLabel(record2.nodeId ?? progress.artifactTableNamespace)}: ${counts}${messageSuffix}`
|
|
18325
18430
|
);
|
|
18326
18431
|
}
|
|
18327
18432
|
return lines;
|
|
@@ -19150,17 +19255,17 @@ function collectDatasetHandleLines(value, path = "result") {
|
|
|
19150
19255
|
return [];
|
|
19151
19256
|
}
|
|
19152
19257
|
if (isDatasetHandle(value)) {
|
|
19153
|
-
const
|
|
19154
|
-
const count = typeof
|
|
19155
|
-
const preview = Array.isArray(
|
|
19258
|
+
const record2 = value;
|
|
19259
|
+
const count = typeof record2.count === "number" ? record2.count : typeof record2.rowCount === "number" ? record2.rowCount : null;
|
|
19260
|
+
const preview = Array.isArray(record2.preview) ? record2.preview : [];
|
|
19156
19261
|
const lines2 = [
|
|
19157
|
-
` dataset ${typeof
|
|
19262
|
+
` dataset ${typeof record2.path === "string" ? record2.path : path}: rows=${count === null ? "-" : formatInteger(count)} preview=${formatInteger(preview.length)}`
|
|
19158
19263
|
];
|
|
19159
|
-
if (typeof
|
|
19160
|
-
lines2.push(` query dataset: ${
|
|
19264
|
+
if (typeof record2.queryDatasetCommand === "string") {
|
|
19265
|
+
lines2.push(` query dataset: ${record2.queryDatasetCommand}`);
|
|
19161
19266
|
}
|
|
19162
|
-
if (typeof
|
|
19163
|
-
lines2.push(` export CSV: ${
|
|
19267
|
+
if (typeof record2.slowExportAsCsvCommand === "string") {
|
|
19268
|
+
lines2.push(` export CSV: ${record2.slowExportAsCsvCommand}`);
|
|
19164
19269
|
}
|
|
19165
19270
|
return lines2;
|
|
19166
19271
|
}
|
|
@@ -19557,8 +19662,8 @@ function withTerminalPlayIdentity(status, playName) {
|
|
|
19557
19662
|
if (!playName.trim() || getPlayRunPackage(status)) {
|
|
19558
19663
|
return status;
|
|
19559
19664
|
}
|
|
19560
|
-
const
|
|
19561
|
-
const hasIdentity = typeof
|
|
19665
|
+
const record2 = status;
|
|
19666
|
+
const hasIdentity = typeof record2.playName === "string" && record2.playName.trim().length > 0 || typeof record2.name === "string" && record2.name.trim().length > 0 || Boolean(getStringField(record2.run, "playName"));
|
|
19562
19667
|
if (hasIdentity) {
|
|
19563
19668
|
return status;
|
|
19564
19669
|
}
|
|
@@ -19671,9 +19776,9 @@ function formatSummaryScalar(value) {
|
|
|
19671
19776
|
}
|
|
19672
19777
|
return null;
|
|
19673
19778
|
}
|
|
19674
|
-
function formatSummaryScalarParts(
|
|
19779
|
+
function formatSummaryScalarParts(record2, skipKeys = /* @__PURE__ */ new Set()) {
|
|
19675
19780
|
const parts = [];
|
|
19676
|
-
for (const [key, value] of Object.entries(
|
|
19781
|
+
for (const [key, value] of Object.entries(record2)) {
|
|
19677
19782
|
if (skipKeys.has(key)) {
|
|
19678
19783
|
continue;
|
|
19679
19784
|
}
|
|
@@ -19700,13 +19805,13 @@ function formatTopValuesPart(value) {
|
|
|
19700
19805
|
return `top_values=${entries.map(([topValue, count]) => `${topValue}=${String(count)}`).join(", ")}`;
|
|
19701
19806
|
}
|
|
19702
19807
|
function formatPackageDatasetSummaryLines(summary, indent2 = " ") {
|
|
19703
|
-
const
|
|
19704
|
-
const columnStats = readRecord(
|
|
19705
|
-
if (!
|
|
19808
|
+
const record2 = readRecord(summary);
|
|
19809
|
+
const columnStats = readRecord(record2?.columnStats);
|
|
19810
|
+
if (!record2 || !columnStats) {
|
|
19706
19811
|
return [];
|
|
19707
19812
|
}
|
|
19708
19813
|
const lines = [];
|
|
19709
|
-
const rowCounts = readRecord(
|
|
19814
|
+
const rowCounts = readRecord(record2.rowCounts);
|
|
19710
19815
|
if (rowCounts) {
|
|
19711
19816
|
const persisted = readNonNegativeInteger(rowCounts.persisted);
|
|
19712
19817
|
const succeeded = readNonNegativeInteger(rowCounts.succeeded);
|
|
@@ -19722,7 +19827,7 @@ function formatPackageDatasetSummaryLines(summary, indent2 = " ") {
|
|
|
19722
19827
|
}
|
|
19723
19828
|
}
|
|
19724
19829
|
const parts = formatSummaryScalarParts(
|
|
19725
|
-
|
|
19830
|
+
record2,
|
|
19726
19831
|
/* @__PURE__ */ new Set(["columnStats", "rowCounts"])
|
|
19727
19832
|
);
|
|
19728
19833
|
if (parts.length > 0) {
|
|
@@ -19752,35 +19857,35 @@ function actionToCommand(action) {
|
|
|
19752
19857
|
if (!action || typeof action !== "object" || Array.isArray(action)) {
|
|
19753
19858
|
return null;
|
|
19754
19859
|
}
|
|
19755
|
-
const
|
|
19756
|
-
if (typeof
|
|
19757
|
-
return
|
|
19860
|
+
const record2 = action;
|
|
19861
|
+
if (typeof record2.command === "string" && record2.command.trim()) {
|
|
19862
|
+
return record2.command.trim();
|
|
19758
19863
|
}
|
|
19759
|
-
if (
|
|
19760
|
-
return `deepline runs get ${
|
|
19864
|
+
if (record2.kind === "deepline_run_inspect" && typeof record2.runId === "string") {
|
|
19865
|
+
return `deepline runs get ${record2.runId} --json`;
|
|
19761
19866
|
}
|
|
19762
|
-
if (
|
|
19763
|
-
return `deepline runs get ${
|
|
19867
|
+
if (record2.kind === "deepline_run_full" && typeof record2.runId === "string") {
|
|
19868
|
+
return `deepline runs get ${record2.runId} --full --json`;
|
|
19764
19869
|
}
|
|
19765
|
-
if (
|
|
19766
|
-
return `deepline runs get ${
|
|
19870
|
+
if (record2.kind === "deepline_run_billing" && typeof record2.runId === "string") {
|
|
19871
|
+
return `deepline runs get ${record2.runId} --full --json | jq '.billing'`;
|
|
19767
19872
|
}
|
|
19768
|
-
if (
|
|
19769
|
-
return `deepline runs export ${
|
|
19770
|
-
|
|
19771
|
-
)} --out ${shellSingleQuote(`${
|
|
19873
|
+
if (record2.kind === "deepline_run_export" && typeof record2.runId === "string" && typeof record2.datasetPath === "string") {
|
|
19874
|
+
return `deepline runs export ${record2.runId} --dataset ${shellSingleQuote(
|
|
19875
|
+
record2.datasetPath
|
|
19876
|
+
)} --out ${shellSingleQuote(`${record2.datasetPath.split(".").pop() || "dataset"}.csv`)}`;
|
|
19772
19877
|
}
|
|
19773
|
-
if (
|
|
19774
|
-
if (typeof
|
|
19775
|
-
return
|
|
19878
|
+
if (record2.kind === "deepline_run_logs") {
|
|
19879
|
+
if (typeof record2.command === "string" && record2.command.trim()) {
|
|
19880
|
+
return record2.command;
|
|
19776
19881
|
}
|
|
19777
|
-
if (typeof
|
|
19778
|
-
return
|
|
19882
|
+
if (typeof record2.runId === "string") {
|
|
19883
|
+
return record2.view === "failed" ? `deepline runs get ${record2.runId} --log-failed --json` : `deepline runs logs ${record2.runId} --json`;
|
|
19779
19884
|
}
|
|
19780
19885
|
}
|
|
19781
|
-
if (
|
|
19782
|
-
const maxRows = typeof
|
|
19783
|
-
return `deepline db query --sql ${shellSingleQuote(
|
|
19886
|
+
if (record2.kind === "deepline_db_query" && typeof record2.sql === "string") {
|
|
19887
|
+
const maxRows = typeof record2.maxRows === "number" && Number.isFinite(record2.maxRows) ? Math.trunc(record2.maxRows) : 20;
|
|
19888
|
+
return `deepline db query --sql ${shellSingleQuote(record2.sql)} --max-rows ${maxRows} --json`;
|
|
19784
19889
|
}
|
|
19785
19890
|
return null;
|
|
19786
19891
|
}
|
|
@@ -20185,12 +20290,12 @@ function exportableSheetRow(row) {
|
|
|
20185
20290
|
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
20186
20291
|
return null;
|
|
20187
20292
|
}
|
|
20188
|
-
const
|
|
20189
|
-
const data =
|
|
20293
|
+
const record2 = row;
|
|
20294
|
+
const data = record2.data;
|
|
20190
20295
|
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
20191
20296
|
return data;
|
|
20192
20297
|
}
|
|
20193
|
-
const fallback = { ...
|
|
20298
|
+
const fallback = { ...record2 };
|
|
20194
20299
|
for (const key of [
|
|
20195
20300
|
"key",
|
|
20196
20301
|
"status",
|
|
@@ -20542,8 +20647,8 @@ var PLAY_SYNTAX_MIGRATION_ERROR_MARKERS = [
|
|
|
20542
20647
|
"ctx.map(...) has been replaced by ctx.dataset(...)",
|
|
20543
20648
|
"Dataset .step(...) has been replaced by .withColumn(...)"
|
|
20544
20649
|
];
|
|
20545
|
-
function stringArrayField(
|
|
20546
|
-
const value =
|
|
20650
|
+
function stringArrayField(record2, key) {
|
|
20651
|
+
const value = record2[key];
|
|
20547
20652
|
if (!Array.isArray(value)) return [];
|
|
20548
20653
|
return value.filter((entry) => typeof entry === "string");
|
|
20549
20654
|
}
|
|
@@ -23716,10 +23821,16 @@ Concepts:
|
|
|
23716
23821
|
Authoring:
|
|
23717
23822
|
Use normal TypeScript interpolation for human-facing strings:
|
|
23718
23823
|
const readyMessage = \`Put \${input.title} through to send-ready.\`;
|
|
23719
|
-
An authored diagram is optional
|
|
23824
|
+
An authored diagram is optional but highly recommended for every new or
|
|
23825
|
+
substantially changed Play. Docflow parses only an explicit
|
|
23720
23826
|
/** @mermaid ... */ block and its // @mermaid-node annotations; ordinary
|
|
23721
23827
|
prose comments are never Docflow syntax. When Docflow is enabled, plays check
|
|
23722
|
-
gives missing diagrams a non-blocking
|
|
23828
|
+
gives missing diagrams a high-priority, non-blocking warning with the exact
|
|
23829
|
+
Mermaid repair steps. Without a diagram, users see only an inferred execution
|
|
23830
|
+
graph rather than a clear business-language map. It is easy to add: write a
|
|
23831
|
+
short top-of-file flowchart, annotate its visible executable steps, then run
|
|
23832
|
+
plays check again. Treat that warning as an authoring task before finishing
|
|
23833
|
+
Play work unless the caller explicitly asks to leave the inferred graph.
|
|
23723
23834
|
|
|
23724
23835
|
Common commands:
|
|
23725
23836
|
deepline plays search email --json
|
|
@@ -26315,7 +26426,7 @@ function emitEnrichDebug(message) {
|
|
|
26315
26426
|
);
|
|
26316
26427
|
}
|
|
26317
26428
|
function sleep6(ms) {
|
|
26318
|
-
return new Promise((
|
|
26429
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
26319
26430
|
}
|
|
26320
26431
|
function enrichExportBackingRowsWaitMs() {
|
|
26321
26432
|
const raw = process.env.DEEPLINE_ENRICH_EXPORT_BACKING_ROWS_WAIT_MS?.trim();
|
|
@@ -26424,9 +26535,9 @@ async function expandCompiledConfigAtFiles(value) {
|
|
|
26424
26535
|
if (!value || typeof value !== "object") {
|
|
26425
26536
|
return value;
|
|
26426
26537
|
}
|
|
26427
|
-
const
|
|
26538
|
+
const record2 = value;
|
|
26428
26539
|
const expanded = {};
|
|
26429
|
-
for (const [key, entry] of Object.entries(
|
|
26540
|
+
for (const [key, entry] of Object.entries(record2)) {
|
|
26430
26541
|
expanded[key] = await expandCompiledConfigAtFiles(entry);
|
|
26431
26542
|
}
|
|
26432
26543
|
for (const field of ["extract_js", "run_if_js"]) {
|
|
@@ -27224,26 +27335,26 @@ function readFirstEnrichDatasetActions(value) {
|
|
|
27224
27335
|
}
|
|
27225
27336
|
return null;
|
|
27226
27337
|
}
|
|
27227
|
-
const
|
|
27228
|
-
const actions = isRecord11(
|
|
27338
|
+
const record2 = candidate;
|
|
27339
|
+
const actions = isRecord11(record2.actions) ? record2.actions : null;
|
|
27229
27340
|
const currentQuery = isRecord11(actions?.queryCurrentTable) ? actions.queryCurrentTable : null;
|
|
27230
27341
|
const legacyQuery = isRecord11(actions?.query) ? actions.query : null;
|
|
27231
27342
|
const query = currentQuery?.kind === "deepline_db_query" ? currentQuery : legacyQuery?.kind === "deepline_db_query" ? legacyQuery : null;
|
|
27232
27343
|
if (query?.kind === "deepline_db_query") {
|
|
27233
27344
|
return {
|
|
27234
|
-
dataset:
|
|
27345
|
+
dataset: record2,
|
|
27235
27346
|
query,
|
|
27236
27347
|
...isRecord11(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
|
|
27237
27348
|
};
|
|
27238
27349
|
}
|
|
27239
|
-
if (options.allowLegacy &&
|
|
27350
|
+
if (options.allowLegacy && record2.kind === "dataset" && typeof record2.queryDatasetCommand === "string" && record2.queryDatasetCommand.trim()) {
|
|
27240
27351
|
return {
|
|
27241
|
-
dataset:
|
|
27242
|
-
queryDatasetCommand:
|
|
27243
|
-
...typeof
|
|
27352
|
+
dataset: record2,
|
|
27353
|
+
queryDatasetCommand: record2.queryDatasetCommand.trim(),
|
|
27354
|
+
...typeof record2.slowExportAsCsvCommand === "string" && record2.slowExportAsCsvCommand.trim() ? { slowExportAsCsvCommand: record2.slowExportAsCsvCommand.trim() } : {}
|
|
27244
27355
|
};
|
|
27245
27356
|
}
|
|
27246
|
-
for (const [key, entry] of Object.entries(
|
|
27357
|
+
for (const [key, entry] of Object.entries(record2)) {
|
|
27247
27358
|
if (key === "preview") {
|
|
27248
27359
|
continue;
|
|
27249
27360
|
}
|
|
@@ -27259,8 +27370,8 @@ function readFirstEnrichDatasetActions(value) {
|
|
|
27259
27370
|
seen.clear();
|
|
27260
27371
|
return walk(value, { allowLegacy: true });
|
|
27261
27372
|
}
|
|
27262
|
-
function actionStringField(
|
|
27263
|
-
const value =
|
|
27373
|
+
function actionStringField(record2, key) {
|
|
27374
|
+
const value = record2[key];
|
|
27264
27375
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
27265
27376
|
}
|
|
27266
27377
|
function parseSqlFromDbQueryCommand(command) {
|
|
@@ -27604,12 +27715,12 @@ function collectStringFields(value, key, output2, depth = 0) {
|
|
|
27604
27715
|
}
|
|
27605
27716
|
return;
|
|
27606
27717
|
}
|
|
27607
|
-
const
|
|
27608
|
-
const direct =
|
|
27718
|
+
const record2 = value;
|
|
27719
|
+
const direct = record2[key];
|
|
27609
27720
|
if (typeof direct === "string" && direct.trim()) {
|
|
27610
27721
|
output2.add(direct.trim());
|
|
27611
27722
|
}
|
|
27612
|
-
for (const child of Object.values(
|
|
27723
|
+
for (const child of Object.values(record2)) {
|
|
27613
27724
|
collectStringFields(child, key, output2, depth + 1);
|
|
27614
27725
|
}
|
|
27615
27726
|
}
|
|
@@ -27795,23 +27906,23 @@ function exportableSheetRow2(row, sourceRowStart = 0) {
|
|
|
27795
27906
|
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
27796
27907
|
return null;
|
|
27797
27908
|
}
|
|
27798
|
-
const
|
|
27799
|
-
const data =
|
|
27909
|
+
const record2 = row;
|
|
27910
|
+
const data = record2.data;
|
|
27800
27911
|
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
27801
27912
|
const exported = { ...data };
|
|
27802
27913
|
applyFailureCellMeta(exported, exported[ENRICH_CELL_META_FIELD], {
|
|
27803
|
-
rowError:
|
|
27914
|
+
rowError: record2.error
|
|
27804
27915
|
});
|
|
27805
|
-
applyFailureCellMeta(exported,
|
|
27806
|
-
applyFailureCellMeta(exported,
|
|
27807
|
-
rowError:
|
|
27916
|
+
applyFailureCellMeta(exported, record2.cellMeta, { rowError: record2.error });
|
|
27917
|
+
applyFailureCellMeta(exported, record2.cellMetaPatch, {
|
|
27918
|
+
rowError: record2.error
|
|
27808
27919
|
});
|
|
27809
|
-
applyFailureCellMeta(exported,
|
|
27810
|
-
rowError:
|
|
27920
|
+
applyFailureCellMeta(exported, record2[ENRICH_CELL_META_PATCH_FIELD], {
|
|
27921
|
+
rowError: record2.error
|
|
27811
27922
|
});
|
|
27812
27923
|
delete exported[ENRICH_CELL_META_FIELD];
|
|
27813
27924
|
delete exported[ENRICH_CELL_META_PATCH_FIELD];
|
|
27814
|
-
const inputIndex = typeof
|
|
27925
|
+
const inputIndex = typeof record2.inputIndex === "number" ? record2.inputIndex : typeof record2.inputIndex === "string" && record2.inputIndex.trim() ? Number(record2.inputIndex) : Number.NaN;
|
|
27815
27926
|
if (Number.isInteger(inputIndex) && inputIndex >= 0) {
|
|
27816
27927
|
if (ENRICH_SOURCE_ROW_INDEX_COLUMN in exported) {
|
|
27817
27928
|
exported[ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN] = exported[ENRICH_SOURCE_ROW_INDEX_COLUMN];
|
|
@@ -27820,18 +27931,18 @@ function exportableSheetRow2(row, sourceRowStart = 0) {
|
|
|
27820
27931
|
}
|
|
27821
27932
|
return exported;
|
|
27822
27933
|
}
|
|
27823
|
-
const fallback = { ...
|
|
27934
|
+
const fallback = { ...record2 };
|
|
27824
27935
|
applyFailureCellMeta(fallback, fallback[ENRICH_CELL_META_FIELD], {
|
|
27825
|
-
rowError:
|
|
27936
|
+
rowError: record2.error
|
|
27826
27937
|
});
|
|
27827
|
-
applyFailureCellMeta(fallback,
|
|
27828
|
-
rowError:
|
|
27938
|
+
applyFailureCellMeta(fallback, record2.cellMeta, {
|
|
27939
|
+
rowError: record2.error
|
|
27829
27940
|
});
|
|
27830
|
-
applyFailureCellMeta(fallback,
|
|
27831
|
-
rowError:
|
|
27941
|
+
applyFailureCellMeta(fallback, record2.cellMetaPatch, {
|
|
27942
|
+
rowError: record2.error
|
|
27832
27943
|
});
|
|
27833
27944
|
applyFailureCellMeta(fallback, fallback[ENRICH_CELL_META_PATCH_FIELD], {
|
|
27834
|
-
rowError:
|
|
27945
|
+
rowError: record2.error
|
|
27835
27946
|
});
|
|
27836
27947
|
for (const key of [
|
|
27837
27948
|
"key",
|
|
@@ -28050,16 +28161,16 @@ function isWaterfallResultMeaningful(value) {
|
|
|
28050
28161
|
return value.some(isWaterfallResultMeaningful);
|
|
28051
28162
|
}
|
|
28052
28163
|
if (value && typeof value === "object") {
|
|
28053
|
-
const
|
|
28054
|
-
const status = typeof
|
|
28164
|
+
const record2 = value;
|
|
28165
|
+
const status = typeof record2.status === "string" ? record2.status.trim().toLowerCase() : "";
|
|
28055
28166
|
if (status === "error" || status === "failed") {
|
|
28056
28167
|
return false;
|
|
28057
28168
|
}
|
|
28058
|
-
if (typeof
|
|
28169
|
+
if (typeof record2.error === "string" && record2.error.trim()) {
|
|
28059
28170
|
return false;
|
|
28060
28171
|
}
|
|
28061
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
28062
|
-
return isWaterfallResultMeaningful(
|
|
28172
|
+
if (Object.prototype.hasOwnProperty.call(record2, "matched_result")) {
|
|
28173
|
+
return isWaterfallResultMeaningful(record2.matched_result);
|
|
28063
28174
|
}
|
|
28064
28175
|
for (const key of [
|
|
28065
28176
|
"value",
|
|
@@ -28074,11 +28185,11 @@ function isWaterfallResultMeaningful(value) {
|
|
|
28074
28185
|
"result",
|
|
28075
28186
|
"data"
|
|
28076
28187
|
]) {
|
|
28077
|
-
if (isWaterfallResultMeaningful(
|
|
28188
|
+
if (isWaterfallResultMeaningful(record2[key])) {
|
|
28078
28189
|
return true;
|
|
28079
28190
|
}
|
|
28080
28191
|
}
|
|
28081
|
-
return Object.entries(
|
|
28192
|
+
return Object.entries(record2).some(
|
|
28082
28193
|
([key, entry]) => !ENRICH_FLATTENED_CONTROL_FIELDS.has(key) && isWaterfallResultMeaningful(entry)
|
|
28083
28194
|
);
|
|
28084
28195
|
}
|
|
@@ -28094,8 +28205,8 @@ function stableRowSnapshot(value) {
|
|
|
28094
28205
|
return `[${value.map(stableRowSnapshot).join(",")}]`;
|
|
28095
28206
|
}
|
|
28096
28207
|
if (value && typeof value === "object") {
|
|
28097
|
-
const
|
|
28098
|
-
return `{${Object.keys(
|
|
28208
|
+
const record2 = value;
|
|
28209
|
+
return `{${Object.keys(record2).sort().map((key) => `${JSON.stringify(key)}:${stableRowSnapshot(record2[key])}`).join(",")}}`;
|
|
28099
28210
|
}
|
|
28100
28211
|
return JSON.stringify(value);
|
|
28101
28212
|
}
|
|
@@ -28682,8 +28793,8 @@ function addEnrichFollowUpCommand(commands, seen, command) {
|
|
|
28682
28793
|
seen.add(normalized);
|
|
28683
28794
|
commands.push({ ...command, command: normalized });
|
|
28684
28795
|
}
|
|
28685
|
-
function datasetSelectorForEnrichCommand(
|
|
28686
|
-
const candidates = [
|
|
28796
|
+
function datasetSelectorForEnrichCommand(record2, fallbackPath) {
|
|
28797
|
+
const candidates = [record2.path, record2.tableNamespace, fallbackPath];
|
|
28687
28798
|
for (const candidate of candidates) {
|
|
28688
28799
|
if (typeof candidate === "string" && candidate.trim()) {
|
|
28689
28800
|
return candidate.trim();
|
|
@@ -28745,19 +28856,19 @@ function collectDatasetFollowUpCommands(value, state) {
|
|
|
28745
28856
|
);
|
|
28746
28857
|
return;
|
|
28747
28858
|
}
|
|
28748
|
-
const
|
|
28749
|
-
const isDataset =
|
|
28859
|
+
const record2 = value;
|
|
28860
|
+
const isDataset = record2.kind === "dataset";
|
|
28750
28861
|
if (isDataset) {
|
|
28751
|
-
const selector = datasetSelectorForEnrichCommand(
|
|
28752
|
-
const labelPath = typeof
|
|
28753
|
-
if (typeof
|
|
28862
|
+
const selector = datasetSelectorForEnrichCommand(record2, state.path);
|
|
28863
|
+
const labelPath = typeof record2.path === "string" && record2.path.trim() ? record2.path.trim() : selector ?? state.path;
|
|
28864
|
+
if (typeof record2.queryDatasetCommand === "string") {
|
|
28754
28865
|
addEnrichFollowUpCommand(state.commands, state.seen, {
|
|
28755
28866
|
label: `query ${labelPath}`,
|
|
28756
28867
|
path: labelPath,
|
|
28757
|
-
command:
|
|
28868
|
+
command: record2.queryDatasetCommand
|
|
28758
28869
|
});
|
|
28759
28870
|
}
|
|
28760
|
-
const exportCommand = typeof
|
|
28871
|
+
const exportCommand = typeof record2.slowExportAsCsvCommand === "string" ? record2.slowExportAsCsvCommand : typeof record2.fullExportCommand === "string" ? record2.fullExportCommand : null;
|
|
28761
28872
|
if (exportCommand) {
|
|
28762
28873
|
addEnrichFollowUpCommand(state.commands, state.seen, {
|
|
28763
28874
|
label: `export ${labelPath}`,
|
|
@@ -28774,7 +28885,7 @@ function collectDatasetFollowUpCommands(value, state) {
|
|
|
28774
28885
|
});
|
|
28775
28886
|
}
|
|
28776
28887
|
}
|
|
28777
|
-
for (const [key, child] of Object.entries(
|
|
28888
|
+
for (const [key, child] of Object.entries(record2)) {
|
|
28778
28889
|
if (key === "preview" || key === "access") {
|
|
28779
28890
|
continue;
|
|
28780
28891
|
}
|
|
@@ -30206,9 +30317,9 @@ function readCodexSessionId(filePath) {
|
|
|
30206
30317
|
)) {
|
|
30207
30318
|
const parsed = parseJsonLine(line);
|
|
30208
30319
|
if (!parsed || typeof parsed !== "object") continue;
|
|
30209
|
-
const
|
|
30210
|
-
const payload =
|
|
30211
|
-
const id =
|
|
30320
|
+
const record2 = parsed;
|
|
30321
|
+
const payload = record2.payload && typeof record2.payload === "object" ? record2.payload : null;
|
|
30322
|
+
const id = record2.type === "session_meta" && typeof payload?.id === "string" ? payload.id : null;
|
|
30212
30323
|
if (id && UUID_RE.test(id)) return id;
|
|
30213
30324
|
}
|
|
30214
30325
|
} catch {
|
|
@@ -30307,15 +30418,15 @@ function messageContentKey(value) {
|
|
|
30307
30418
|
if (!Array.isArray(content)) return null;
|
|
30308
30419
|
return content.map((block) => {
|
|
30309
30420
|
if (!block || typeof block !== "object") return String(block);
|
|
30310
|
-
const
|
|
30311
|
-
const type = String(
|
|
30421
|
+
const record2 = block;
|
|
30422
|
+
const type = String(record2.type ?? "");
|
|
30312
30423
|
if (type === "tool_use") {
|
|
30313
|
-
return `tool_use:${String(
|
|
30424
|
+
return `tool_use:${String(record2.name ?? "")}:${String(record2.id ?? "")}`;
|
|
30314
30425
|
}
|
|
30315
30426
|
if (type === "tool_result") {
|
|
30316
|
-
return `tool_result:${String(
|
|
30427
|
+
return `tool_result:${String(record2.tool_use_id ?? "")}`;
|
|
30317
30428
|
}
|
|
30318
|
-
return String(
|
|
30429
|
+
return String(record2.text ?? type);
|
|
30319
30430
|
}).join("\n");
|
|
30320
30431
|
}
|
|
30321
30432
|
function dedupConsecutiveEvents(raw) {
|
|
@@ -30330,9 +30441,9 @@ function dedupConsecutiveEvents(raw) {
|
|
|
30330
30441
|
index += 1;
|
|
30331
30442
|
continue;
|
|
30332
30443
|
}
|
|
30333
|
-
const
|
|
30334
|
-
const eventType = String(
|
|
30335
|
-
const eventKey = messageContentKey(
|
|
30444
|
+
const record2 = event;
|
|
30445
|
+
const eventType = String(record2.type ?? "");
|
|
30446
|
+
const eventKey = messageContentKey(record2);
|
|
30336
30447
|
if (!["user", "assistant"].includes(eventType) || !eventKey) {
|
|
30337
30448
|
output2.push(rawLines[index] ?? "");
|
|
30338
30449
|
index += 1;
|
|
@@ -30351,9 +30462,9 @@ function dedupConsecutiveEvents(raw) {
|
|
|
30351
30462
|
cursor += 1;
|
|
30352
30463
|
}
|
|
30353
30464
|
if (runCount > 1) {
|
|
30354
|
-
|
|
30355
|
-
|
|
30356
|
-
output2.push(JSON.stringify(
|
|
30465
|
+
record2._repeat_count = runCount;
|
|
30466
|
+
record2._repeat_summary = `${runCount} consecutive identical ${eventType} messages collapsed`;
|
|
30467
|
+
output2.push(JSON.stringify(record2));
|
|
30357
30468
|
index = cursor;
|
|
30358
30469
|
continue;
|
|
30359
30470
|
}
|
|
@@ -30398,9 +30509,9 @@ function selectiveCompactToolResults(raw) {
|
|
|
30398
30509
|
lines.push(line);
|
|
30399
30510
|
continue;
|
|
30400
30511
|
}
|
|
30401
|
-
const
|
|
30402
|
-
if (
|
|
30403
|
-
const message =
|
|
30512
|
+
const record2 = parsed;
|
|
30513
|
+
if (record2.type === "user") {
|
|
30514
|
+
const message = record2.message;
|
|
30404
30515
|
const content = message && typeof message === "object" ? message.content : null;
|
|
30405
30516
|
if (Array.isArray(content)) {
|
|
30406
30517
|
message.content = content.map(
|
|
@@ -30408,7 +30519,7 @@ function selectiveCompactToolResults(raw) {
|
|
|
30408
30519
|
);
|
|
30409
30520
|
}
|
|
30410
30521
|
}
|
|
30411
|
-
lines.push(JSON.stringify(
|
|
30522
|
+
lines.push(JSON.stringify(record2));
|
|
30412
30523
|
}
|
|
30413
30524
|
return Buffer.from(lines.length > 0 ? `${lines.join("\n")}
|
|
30414
30525
|
` : "", "utf8");
|
|
@@ -30434,15 +30545,15 @@ function compactCodexEvents(raw) {
|
|
|
30434
30545
|
lines.push(rawLines[index] ?? "");
|
|
30435
30546
|
return;
|
|
30436
30547
|
}
|
|
30437
|
-
const
|
|
30438
|
-
if (
|
|
30439
|
-
const payload =
|
|
30548
|
+
const record2 = event;
|
|
30549
|
+
if (record2.type === "world_state") return;
|
|
30550
|
+
const payload = record2.payload;
|
|
30440
30551
|
const payloadType = payload && typeof payload === "object" ? String(payload.type ?? "") : "";
|
|
30441
30552
|
if (payloadType === "token_count" && index !== lastTokenCountIndex) return;
|
|
30442
30553
|
if (payloadType === "custom_tool_call_output" || payloadType === "function_call_output" || payloadType === "tool_search_output") {
|
|
30443
30554
|
const record_payload = payload;
|
|
30444
30555
|
record_payload.output = compactEventValue(record_payload.output);
|
|
30445
|
-
lines.push(JSON.stringify(
|
|
30556
|
+
lines.push(JSON.stringify(record2));
|
|
30446
30557
|
return;
|
|
30447
30558
|
}
|
|
30448
30559
|
lines.push(rawLines[index] ?? "");
|
|
@@ -30905,8 +31016,325 @@ Examples:
|
|
|
30905
31016
|
}
|
|
30906
31017
|
|
|
30907
31018
|
// src/cli/commands/monitors.ts
|
|
30908
|
-
import {
|
|
31019
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
31020
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync12 } from "fs";
|
|
31021
|
+
import { resolve as resolve14 } from "path";
|
|
30909
31022
|
import { createInterface } from "readline/promises";
|
|
31023
|
+
|
|
31024
|
+
// src/monitor-fleet-contract.ts
|
|
31025
|
+
var MONITOR_FLEET_MAX_MEMBERS = 1e3;
|
|
31026
|
+
var MONITOR_FLEET_AUTHORING_CONTRACT_EDITION = 1;
|
|
31027
|
+
var SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS = [
|
|
31028
|
+
MONITOR_FLEET_AUTHORING_CONTRACT_EDITION
|
|
31029
|
+
];
|
|
31030
|
+
var MONITOR_FLEET_REMOVAL_GRACE_MS = 7 * 24 * 60 * 6e4;
|
|
31031
|
+
var MONITOR_FLEET_DOCUMENTATION = {
|
|
31032
|
+
summary: "A Monitor Fleet keeps one bounded, sticky set of ordinary monitors aligned with Customer DB rows.",
|
|
31033
|
+
authoredFields: {
|
|
31034
|
+
id: "Stable lowercase fleet id used by sync, pause, resume, and deactivate.",
|
|
31035
|
+
source: "Customer DB table, unique row key, and optional equality filters that select candidate rows.",
|
|
31036
|
+
member: "Ordinary monitor tool, stable key template, and payload evaluated for each selected source row.",
|
|
31037
|
+
selection: "Deterministic ranking and an active-member limit between 1 and 1,000."
|
|
31038
|
+
},
|
|
31039
|
+
fixedPolicy: {
|
|
31040
|
+
cadence: "daily",
|
|
31041
|
+
membership: "sticky",
|
|
31042
|
+
removalGrace: "7d",
|
|
31043
|
+
onRemoved: "deactivate",
|
|
31044
|
+
ownership: "A Fleet may adopt a same-tool ordinary monitor with its deterministic member key. The first Fleet claim wins; another Fleet or a different tool receives a conflict.",
|
|
31045
|
+
billing: "No Fleet fee, permit, or renewal. Dry-run reports ordinary monitor lifecycle charges due now."
|
|
31046
|
+
},
|
|
31047
|
+
stickyMembership: "Ranking fills vacancies but never replaces a current member merely because another row ranks higher.",
|
|
31048
|
+
columnExpression: 'Use { "$fleet": "column", "name": "column_name" } in a member key or payload to read a value from each source row.'
|
|
31049
|
+
};
|
|
31050
|
+
function record(value) {
|
|
31051
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
31052
|
+
}
|
|
31053
|
+
function identifier(value) {
|
|
31054
|
+
return typeof value === "string" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
|
|
31055
|
+
}
|
|
31056
|
+
function exactKeys(input2, keys, path, issues) {
|
|
31057
|
+
if (!input2) return;
|
|
31058
|
+
for (const key of Object.keys(input2)) {
|
|
31059
|
+
if (keys.includes(key)) continue;
|
|
31060
|
+
issues.push({
|
|
31061
|
+
path: path ? `${path}.${key}` : key,
|
|
31062
|
+
code: "unknown_fleet_field",
|
|
31063
|
+
message: `${path || "Fleet"} does not accept '${key}'.`
|
|
31064
|
+
});
|
|
31065
|
+
}
|
|
31066
|
+
}
|
|
31067
|
+
function jsonValue(value, path, issues) {
|
|
31068
|
+
if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
|
|
31069
|
+
return;
|
|
31070
|
+
}
|
|
31071
|
+
if (Array.isArray(value)) {
|
|
31072
|
+
value.forEach((item, index) => jsonValue(item, `${path}.${index}`, issues));
|
|
31073
|
+
return;
|
|
31074
|
+
}
|
|
31075
|
+
const input2 = record(value);
|
|
31076
|
+
if (!input2) {
|
|
31077
|
+
issues.push({
|
|
31078
|
+
path,
|
|
31079
|
+
code: "invalid_fleet_json_value",
|
|
31080
|
+
message: "Fleet payload values must be JSON values."
|
|
31081
|
+
});
|
|
31082
|
+
return;
|
|
31083
|
+
}
|
|
31084
|
+
for (const [key, item] of Object.entries(input2)) {
|
|
31085
|
+
jsonValue(item, `${path}.${key}`, issues);
|
|
31086
|
+
}
|
|
31087
|
+
}
|
|
31088
|
+
function validateExpression(value, path, issues) {
|
|
31089
|
+
const input2 = record(value);
|
|
31090
|
+
if (!input2 || input2.$fleet !== "column" || !identifier(input2.name)) {
|
|
31091
|
+
issues.push({
|
|
31092
|
+
path,
|
|
31093
|
+
code: "invalid_fleet_expression",
|
|
31094
|
+
message: "Fleet expressions must be an exact tagged column reference."
|
|
31095
|
+
});
|
|
31096
|
+
return;
|
|
31097
|
+
}
|
|
31098
|
+
exactKeys(input2, ["$fleet", "name"], path, issues);
|
|
31099
|
+
}
|
|
31100
|
+
function walkPayload(value, path, issues) {
|
|
31101
|
+
if (Array.isArray(value)) {
|
|
31102
|
+
value.forEach(
|
|
31103
|
+
(item, index) => walkPayload(item, `${path}.${index}`, issues)
|
|
31104
|
+
);
|
|
31105
|
+
return;
|
|
31106
|
+
}
|
|
31107
|
+
const input2 = record(value);
|
|
31108
|
+
if (!input2) return;
|
|
31109
|
+
if ("$fleet" in input2) {
|
|
31110
|
+
validateExpression(input2, path, issues);
|
|
31111
|
+
return;
|
|
31112
|
+
}
|
|
31113
|
+
for (const [key, item] of Object.entries(input2)) {
|
|
31114
|
+
walkPayload(item, `${path}.${key}`, issues);
|
|
31115
|
+
}
|
|
31116
|
+
}
|
|
31117
|
+
function validateMonitorFleetDefinition(value) {
|
|
31118
|
+
const issues = [];
|
|
31119
|
+
const input2 = record(value);
|
|
31120
|
+
if (!input2) {
|
|
31121
|
+
return {
|
|
31122
|
+
valid: false,
|
|
31123
|
+
issues: [
|
|
31124
|
+
{
|
|
31125
|
+
path: "",
|
|
31126
|
+
code: "invalid_fleet",
|
|
31127
|
+
message: "Fleet must be an object."
|
|
31128
|
+
}
|
|
31129
|
+
]
|
|
31130
|
+
};
|
|
31131
|
+
}
|
|
31132
|
+
exactKeys(input2, ["id", "source", "member", "selection"], "", issues);
|
|
31133
|
+
if (typeof input2.id !== "string" || !/^[a-z][a-z0-9-]{0,199}$/.test(input2.id)) {
|
|
31134
|
+
issues.push({
|
|
31135
|
+
path: "id",
|
|
31136
|
+
code: "invalid_fleet_id",
|
|
31137
|
+
message: "Fleet id must be lowercase kebab-case."
|
|
31138
|
+
});
|
|
31139
|
+
}
|
|
31140
|
+
const source = record(input2.source);
|
|
31141
|
+
exactKeys(
|
|
31142
|
+
source,
|
|
31143
|
+
["kind", "schema", "table", "key", "where"],
|
|
31144
|
+
"source",
|
|
31145
|
+
issues
|
|
31146
|
+
);
|
|
31147
|
+
if (!source || source.kind !== "customer_db_table") {
|
|
31148
|
+
issues.push({
|
|
31149
|
+
path: "source.kind",
|
|
31150
|
+
code: "invalid_fleet_source",
|
|
31151
|
+
message: "Beta fleets require customer_db_table."
|
|
31152
|
+
});
|
|
31153
|
+
}
|
|
31154
|
+
if (!identifier(source?.schema) || !identifier(source?.table)) {
|
|
31155
|
+
issues.push({
|
|
31156
|
+
path: "source",
|
|
31157
|
+
code: "invalid_fleet_table",
|
|
31158
|
+
message: "Source schema and table must be SQL identifiers."
|
|
31159
|
+
});
|
|
31160
|
+
}
|
|
31161
|
+
const sourceKey = record(source?.key);
|
|
31162
|
+
exactKeys(sourceKey, ["column", "type"], "source.key", issues);
|
|
31163
|
+
if (!sourceKey || !identifier(sourceKey.column) || !["text", "uuid", "int4", "int8"].includes(String(sourceKey.type))) {
|
|
31164
|
+
issues.push({
|
|
31165
|
+
path: "source.key",
|
|
31166
|
+
code: "invalid_fleet_source_key",
|
|
31167
|
+
message: "Source key must name a supported typed column."
|
|
31168
|
+
});
|
|
31169
|
+
}
|
|
31170
|
+
if (source?.where !== void 0) {
|
|
31171
|
+
const where = record(source.where);
|
|
31172
|
+
if (!where) {
|
|
31173
|
+
issues.push({
|
|
31174
|
+
path: "source.where",
|
|
31175
|
+
code: "invalid_fleet_where",
|
|
31176
|
+
message: "source.where must be an object of equality values."
|
|
31177
|
+
});
|
|
31178
|
+
} else {
|
|
31179
|
+
for (const [column, expected] of Object.entries(where)) {
|
|
31180
|
+
if (!identifier(column)) {
|
|
31181
|
+
issues.push({
|
|
31182
|
+
path: `source.where.${column}`,
|
|
31183
|
+
code: "invalid_fleet_where_column",
|
|
31184
|
+
message: "source.where keys must be SQL identifiers."
|
|
31185
|
+
});
|
|
31186
|
+
}
|
|
31187
|
+
if (expected !== null && typeof expected !== "string" && typeof expected !== "boolean" && !(typeof expected === "number" && Number.isFinite(expected))) {
|
|
31188
|
+
issues.push({
|
|
31189
|
+
path: `source.where.${column}`,
|
|
31190
|
+
code: "invalid_fleet_where_value",
|
|
31191
|
+
message: "source.where values must be finite JSON scalars or null."
|
|
31192
|
+
});
|
|
31193
|
+
}
|
|
31194
|
+
}
|
|
31195
|
+
}
|
|
31196
|
+
}
|
|
31197
|
+
const member = record(input2.member);
|
|
31198
|
+
exactKeys(member, ["tool", "key", "payload"], "member", issues);
|
|
31199
|
+
const key = record(member?.key);
|
|
31200
|
+
if (!member || typeof member.tool !== "string" || !member.tool.trim()) {
|
|
31201
|
+
issues.push({
|
|
31202
|
+
path: "member.tool",
|
|
31203
|
+
code: "invalid_fleet_tool",
|
|
31204
|
+
message: "Member tool is required."
|
|
31205
|
+
});
|
|
31206
|
+
}
|
|
31207
|
+
if (!key || key.$fleet !== "template" || !Array.isArray(key.parts) || key.parts.length === 0) {
|
|
31208
|
+
issues.push({
|
|
31209
|
+
path: "member.key",
|
|
31210
|
+
code: "invalid_fleet_key",
|
|
31211
|
+
message: "Member key must be a tagged fleet template."
|
|
31212
|
+
});
|
|
31213
|
+
} else {
|
|
31214
|
+
exactKeys(key, ["$fleet", "parts"], "member.key", issues);
|
|
31215
|
+
for (const [index, part] of key.parts.entries()) {
|
|
31216
|
+
if (typeof part !== "string")
|
|
31217
|
+
validateExpression(part, `member.key.parts.${index}`, issues);
|
|
31218
|
+
}
|
|
31219
|
+
if (sourceKey && !key.parts.some(
|
|
31220
|
+
(part) => record(part)?.$fleet === "column" && record(part)?.name === sourceKey.column
|
|
31221
|
+
)) {
|
|
31222
|
+
issues.push({
|
|
31223
|
+
path: "member.key.parts",
|
|
31224
|
+
code: "fleet_key_missing_source_key",
|
|
31225
|
+
message: "Member key must include the source key column."
|
|
31226
|
+
});
|
|
31227
|
+
}
|
|
31228
|
+
}
|
|
31229
|
+
if (!member || !("payload" in member)) {
|
|
31230
|
+
issues.push({
|
|
31231
|
+
path: "member.payload",
|
|
31232
|
+
code: "invalid_fleet_payload",
|
|
31233
|
+
message: "Member payload is required."
|
|
31234
|
+
});
|
|
31235
|
+
} else {
|
|
31236
|
+
jsonValue(member.payload, "member.payload", issues);
|
|
31237
|
+
}
|
|
31238
|
+
walkPayload(member?.payload, "member.payload", issues);
|
|
31239
|
+
const selection = record(input2.selection);
|
|
31240
|
+
exactKeys(selection, ["limit", "orderBy", "membership"], "selection", issues);
|
|
31241
|
+
if (!selection || !Number.isSafeInteger(selection.limit) || Number(selection.limit) < 1 || Number(selection.limit) > MONITOR_FLEET_MAX_MEMBERS) {
|
|
31242
|
+
issues.push({
|
|
31243
|
+
path: "selection.limit",
|
|
31244
|
+
code: "MONITOR_FLEET_LIMIT_EXCEEDED",
|
|
31245
|
+
message: "selection.limit must be between 1 and 1,000."
|
|
31246
|
+
});
|
|
31247
|
+
}
|
|
31248
|
+
if (selection?.membership !== "sticky") {
|
|
31249
|
+
issues.push({
|
|
31250
|
+
path: "selection.membership",
|
|
31251
|
+
code: "invalid_fleet_membership",
|
|
31252
|
+
message: `Fleet membership is fixed to ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.membership}. ${MONITOR_FLEET_DOCUMENTATION.stickyMembership}`
|
|
31253
|
+
});
|
|
31254
|
+
}
|
|
31255
|
+
const orderBy = selection?.orderBy;
|
|
31256
|
+
if (!Array.isArray(orderBy) || orderBy.length === 0) {
|
|
31257
|
+
issues.push({
|
|
31258
|
+
path: "selection.orderBy",
|
|
31259
|
+
code: "invalid_fleet_order",
|
|
31260
|
+
message: "At least one deterministic order field is required."
|
|
31261
|
+
});
|
|
31262
|
+
} else {
|
|
31263
|
+
const orderColumns = /* @__PURE__ */ new Set();
|
|
31264
|
+
for (const [index, order] of orderBy.entries()) {
|
|
31265
|
+
const item = record(order);
|
|
31266
|
+
exactKeys(
|
|
31267
|
+
item,
|
|
31268
|
+
["column", "direction"],
|
|
31269
|
+
`selection.orderBy.${index}`,
|
|
31270
|
+
issues
|
|
31271
|
+
);
|
|
31272
|
+
if (!item || !identifier(item.column) || !["asc", "desc"].includes(String(item.direction))) {
|
|
31273
|
+
issues.push({
|
|
31274
|
+
path: `selection.orderBy.${index}`,
|
|
31275
|
+
code: "invalid_fleet_order",
|
|
31276
|
+
message: "Order fields need a column and asc/desc direction."
|
|
31277
|
+
});
|
|
31278
|
+
} else if (orderColumns.has(item.column)) {
|
|
31279
|
+
issues.push({
|
|
31280
|
+
path: `selection.orderBy.${index}.column`,
|
|
31281
|
+
code: "duplicate_fleet_order_column",
|
|
31282
|
+
message: "Each selection order column may appear only once."
|
|
31283
|
+
});
|
|
31284
|
+
} else {
|
|
31285
|
+
orderColumns.add(item.column);
|
|
31286
|
+
}
|
|
31287
|
+
}
|
|
31288
|
+
if (sourceKey && record(orderBy.at(-1))?.column !== sourceKey.column) {
|
|
31289
|
+
issues.push({
|
|
31290
|
+
path: "selection.orderBy",
|
|
31291
|
+
code: "fleet_order_missing_key",
|
|
31292
|
+
message: "The final order field must be the source key."
|
|
31293
|
+
});
|
|
31294
|
+
}
|
|
31295
|
+
}
|
|
31296
|
+
for (const removedOption of ["spendLimits", "lifecycle", "reconciliation"]) {
|
|
31297
|
+
if (removedOption in input2) {
|
|
31298
|
+
issues.push({
|
|
31299
|
+
path: removedOption,
|
|
31300
|
+
code: "unsupported_fleet_option",
|
|
31301
|
+
message: `${removedOption} is fixed by Monitor Fleets and must be omitted. Fleets sync ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.cadence} and ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.onRemoved} members after ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.removalGrace} absent from the source.`
|
|
31302
|
+
});
|
|
31303
|
+
}
|
|
31304
|
+
}
|
|
31305
|
+
return issues.length === 0 ? { valid: true, definition: value, issues } : { valid: false, issues };
|
|
31306
|
+
}
|
|
31307
|
+
function admitMonitorFleetAuthoringContract(value, edition = MONITOR_FLEET_AUTHORING_CONTRACT_EDITION) {
|
|
31308
|
+
if (!SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS.includes(
|
|
31309
|
+
edition
|
|
31310
|
+
)) {
|
|
31311
|
+
return {
|
|
31312
|
+
valid: false,
|
|
31313
|
+
issues: [
|
|
31314
|
+
{
|
|
31315
|
+
path: "authoring_contract_edition",
|
|
31316
|
+
code: "unsupported_fleet_authoring_contract_edition",
|
|
31317
|
+
message: `Monitor Fleet authoring contract edition ${edition} is not supported.`
|
|
31318
|
+
}
|
|
31319
|
+
]
|
|
31320
|
+
};
|
|
31321
|
+
}
|
|
31322
|
+
const result = validateMonitorFleetDefinition(value);
|
|
31323
|
+
return result.valid && result.definition ? {
|
|
31324
|
+
valid: true,
|
|
31325
|
+
contract: {
|
|
31326
|
+
edition,
|
|
31327
|
+
// JSON cloning prevents later caller mutation from changing the
|
|
31328
|
+
// admitted snapshot.
|
|
31329
|
+
definition: JSON.parse(
|
|
31330
|
+
JSON.stringify(result.definition)
|
|
31331
|
+
)
|
|
31332
|
+
},
|
|
31333
|
+
issues: []
|
|
31334
|
+
} : { valid: false, issues: result.issues };
|
|
31335
|
+
}
|
|
31336
|
+
|
|
31337
|
+
// src/cli/commands/monitors.ts
|
|
30910
31338
|
var JSON_OPTION_DESCRIPTION = "Emit JSON output. Also automatic when stdout is piped";
|
|
30911
31339
|
function withJsonOption(command) {
|
|
30912
31340
|
return command.option("--json", JSON_OPTION_DESCRIPTION);
|
|
@@ -30928,6 +31356,7 @@ var MonitorDryRunUnsupportedError = class extends Error {
|
|
|
30928
31356
|
};
|
|
30929
31357
|
function monitorsErrorExitCode(error) {
|
|
30930
31358
|
if (error instanceof MonitorsUsageError) return 2;
|
|
31359
|
+
if (error instanceof MonitorFleetStateError) return 6;
|
|
30931
31360
|
if (error instanceof AuthError) return 3;
|
|
30932
31361
|
if (error instanceof DeeplineError) {
|
|
30933
31362
|
const status = error.statusCode;
|
|
@@ -30938,12 +31367,14 @@ function monitorsErrorExitCode(error) {
|
|
|
30938
31367
|
}
|
|
30939
31368
|
return 5;
|
|
30940
31369
|
}
|
|
30941
|
-
function monitorsFailureNextCommand(error, exitCode) {
|
|
31370
|
+
function monitorsFailureNextCommand(error, exitCode, options) {
|
|
31371
|
+
if (error instanceof MonitorFleetStateError) return error.next;
|
|
30942
31372
|
if (error instanceof DeeplineError) {
|
|
30943
31373
|
const response = asRecord2(asRecord2(error.details)?.response);
|
|
30944
|
-
const
|
|
30945
|
-
if (
|
|
31374
|
+
const serverNext = asString(response?.next) ?? asString(response?.next_action);
|
|
31375
|
+
if (serverNext) return serverNext;
|
|
30946
31376
|
}
|
|
31377
|
+
if (exitCode === 5 && options?.retryCommand) return options.retryCommand;
|
|
30947
31378
|
if (error instanceof DeeplineError && error.code === "monitor_access_required") {
|
|
30948
31379
|
return "deepline monitors status";
|
|
30949
31380
|
}
|
|
@@ -30969,9 +31400,10 @@ function readValidationIssues(error) {
|
|
|
30969
31400
|
];
|
|
30970
31401
|
});
|
|
30971
31402
|
}
|
|
30972
|
-
function reportMonitorsFailure(error) {
|
|
31403
|
+
function reportMonitorsFailure(error, options) {
|
|
30973
31404
|
const exitCode = monitorsErrorExitCode(error);
|
|
30974
|
-
const next = monitorsFailureNextCommand(error, exitCode);
|
|
31405
|
+
const next = monitorsFailureNextCommand(error, exitCode, options);
|
|
31406
|
+
const retrySafe = exitCode === 5 && options?.retryCommand !== void 0;
|
|
30975
31407
|
const wantsJson = shouldEmitJson(process.argv.includes("--json"));
|
|
30976
31408
|
if (wantsJson) {
|
|
30977
31409
|
const payload = errorToJsonPayload(error);
|
|
@@ -30979,10 +31411,15 @@ function reportMonitorsFailure(error) {
|
|
|
30979
31411
|
ok: false,
|
|
30980
31412
|
exitCode,
|
|
30981
31413
|
...next ? { next } : {},
|
|
30982
|
-
|
|
31414
|
+
...retrySafe ? { retry_safe: true } : {},
|
|
31415
|
+
error: retrySafe ? {
|
|
31416
|
+
...payload.error,
|
|
31417
|
+
message: `${payload.error.message} ${FLEET_RETRY_SAFE_NOTE}`
|
|
31418
|
+
} : payload.error
|
|
30983
31419
|
});
|
|
30984
31420
|
} else {
|
|
30985
|
-
const
|
|
31421
|
+
const base = error instanceof Error ? error.message : String(error);
|
|
31422
|
+
const message = retrySafe ? `${base} ${FLEET_RETRY_SAFE_NOTE}` : base;
|
|
30986
31423
|
process.stderr.write(`Error: ${message}
|
|
30987
31424
|
`);
|
|
30988
31425
|
for (const issue of readValidationIssues(error)) {
|
|
@@ -31533,6 +31970,724 @@ async function handleMonitorsDeploy(definition, options) {
|
|
|
31533
31970
|
text: renderMonitorDeployCompletion(payload)
|
|
31534
31971
|
});
|
|
31535
31972
|
}
|
|
31973
|
+
function fleetIntegerOption(raw, flag) {
|
|
31974
|
+
if (raw === void 0) return void 0;
|
|
31975
|
+
const value = Number(raw);
|
|
31976
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
31977
|
+
throw new MonitorsUsageError(`${flag} must be a non-negative integer.`);
|
|
31978
|
+
}
|
|
31979
|
+
return value;
|
|
31980
|
+
}
|
|
31981
|
+
function fleetIdempotencyKey(operation, supplied) {
|
|
31982
|
+
const normalized = supplied?.trim();
|
|
31983
|
+
if (supplied !== void 0 && !normalized) {
|
|
31984
|
+
throw new MonitorsUsageError("--idempotency-key must not be empty.");
|
|
31985
|
+
}
|
|
31986
|
+
return normalized ?? `monitor-fleet-${operation}-${randomUUID5()}`;
|
|
31987
|
+
}
|
|
31988
|
+
var FLEET_COUNT_KEYS = [
|
|
31989
|
+
"pending",
|
|
31990
|
+
"submitting",
|
|
31991
|
+
"rate_limited",
|
|
31992
|
+
"settled",
|
|
31993
|
+
"blocked",
|
|
31994
|
+
"failed"
|
|
31995
|
+
];
|
|
31996
|
+
var FLEET_DEFAULT_WAIT_MS = 10 * 6e4;
|
|
31997
|
+
var FLEET_POLL_INTERVAL_MS = 2e3;
|
|
31998
|
+
var FLEET_PLAIN_PROGRESS_INTERVAL_MS = 15e3;
|
|
31999
|
+
var FLEET_RETRY_SAFE_NOTE = "Safe to retry \u2014 every fleet command is idempotent.";
|
|
32000
|
+
var MONITOR_FLEET_LIFECYCLE = [
|
|
32001
|
+
{
|
|
32002
|
+
step: 1,
|
|
32003
|
+
what: "Write a definition file you can read and edit.",
|
|
32004
|
+
command: "deepline monitors fleets init <fleet-id> --source public.accounts --key account_id --tool <tool> --payload '<json>' --out fleet.json"
|
|
32005
|
+
},
|
|
32006
|
+
{
|
|
32007
|
+
step: 2,
|
|
32008
|
+
what: "See the plan and the credits before anything changes.",
|
|
32009
|
+
command: "deepline monitors fleets sync --file fleet.json --dry-run"
|
|
32010
|
+
},
|
|
32011
|
+
{
|
|
32012
|
+
step: 3,
|
|
32013
|
+
what: "Apply it and wait for the server to call it converged.",
|
|
32014
|
+
command: "deepline monitors fleets sync --file fleet.json --wait"
|
|
32015
|
+
},
|
|
32016
|
+
{
|
|
32017
|
+
step: 4,
|
|
32018
|
+
what: "Read live state; add --drift to see what has not settled.",
|
|
32019
|
+
command: "deepline monitors fleets get <fleet-id>"
|
|
32020
|
+
}
|
|
32021
|
+
];
|
|
32022
|
+
var MONITOR_FLEET_COMMANDS = [
|
|
32023
|
+
{ name: "init", summary: "Write a Fleet definition JSON file." },
|
|
32024
|
+
{
|
|
32025
|
+
name: "sync",
|
|
32026
|
+
summary: "Create or re-plan a fleet from a definition file or its stored config."
|
|
32027
|
+
},
|
|
32028
|
+
{
|
|
32029
|
+
name: "get",
|
|
32030
|
+
summary: "Read one fleet, list every fleet, or inspect drift."
|
|
32031
|
+
},
|
|
32032
|
+
{
|
|
32033
|
+
name: "deactivate",
|
|
32034
|
+
summary: "Deactivate a fleet and the monitors it owns."
|
|
32035
|
+
}
|
|
32036
|
+
];
|
|
32037
|
+
var MONITOR_FLEET_AGENT_NOTES = [
|
|
32038
|
+
"Add --json for stable output; stdout is always exactly one JSON object.",
|
|
32039
|
+
"Every error includes a runnable `next` command \u2014 run it, do not guess.",
|
|
32040
|
+
"Exit 5 = retry the same command; 6 = inspect counts with `get --drift`; 7 = change the request."
|
|
32041
|
+
];
|
|
32042
|
+
var MONITOR_FLEET_HELP_EPILOG = `
|
|
32043
|
+
Agent notes:
|
|
32044
|
+
${MONITOR_FLEET_AGENT_NOTES.join("\n ")}
|
|
32045
|
+
`;
|
|
32046
|
+
var MonitorFleetStateError = class extends Error {
|
|
32047
|
+
code;
|
|
32048
|
+
next;
|
|
32049
|
+
constructor(input2) {
|
|
32050
|
+
super(input2.message);
|
|
32051
|
+
this.name = "MonitorFleetStateError";
|
|
32052
|
+
this.code = input2.code;
|
|
32053
|
+
this.next = input2.next;
|
|
32054
|
+
}
|
|
32055
|
+
};
|
|
32056
|
+
function fleetCounts(payload) {
|
|
32057
|
+
const raw = asRecord2(payload.counts) ?? {};
|
|
32058
|
+
const counts = {};
|
|
32059
|
+
for (const key of FLEET_COUNT_KEYS) {
|
|
32060
|
+
counts[key] = asFiniteNumber(raw[key]) ?? 0;
|
|
32061
|
+
}
|
|
32062
|
+
return counts;
|
|
32063
|
+
}
|
|
32064
|
+
function fleetShellArg(value) {
|
|
32065
|
+
return /^[A-Za-z0-9._/@:=-]+$/.test(value) ? value : `'${value.replaceAll("'", `'\\''`)}'`;
|
|
32066
|
+
}
|
|
32067
|
+
function fleetJsonFlag(options) {
|
|
32068
|
+
return options.json ? ["--json"] : [];
|
|
32069
|
+
}
|
|
32070
|
+
function fleetTimeoutMs(raw) {
|
|
32071
|
+
if (raw === void 0) return FLEET_DEFAULT_WAIT_MS;
|
|
32072
|
+
const match = /^(\d+)(ms|s|m|h)?$/.exec(raw.trim());
|
|
32073
|
+
if (!match) {
|
|
32074
|
+
throw new MonitorsUsageError(
|
|
32075
|
+
"--timeout must be a duration like 500ms, 90s, 10m, or 1h (a bare number is seconds)."
|
|
32076
|
+
);
|
|
32077
|
+
}
|
|
32078
|
+
const value = Number(match[1]);
|
|
32079
|
+
if (!value) {
|
|
32080
|
+
throw new MonitorsUsageError("--timeout must be greater than zero.");
|
|
32081
|
+
}
|
|
32082
|
+
const unit = match[2] ?? "s";
|
|
32083
|
+
const factor = unit === "ms" ? 1 : unit === "s" ? 1e3 : unit === "m" ? 6e4 : 36e5;
|
|
32084
|
+
return value * factor;
|
|
32085
|
+
}
|
|
32086
|
+
function fleetServerNext(payload) {
|
|
32087
|
+
return asString(payload.next) ?? asString(payload.next_action);
|
|
32088
|
+
}
|
|
32089
|
+
function fleetStatus(payload) {
|
|
32090
|
+
return asString(payload.status);
|
|
32091
|
+
}
|
|
32092
|
+
function fleetProgressReporter() {
|
|
32093
|
+
const interactive = process.stderr.isTTY === true;
|
|
32094
|
+
let wrote = false;
|
|
32095
|
+
let lastPlainAt = 0;
|
|
32096
|
+
return {
|
|
32097
|
+
report: (payload) => {
|
|
32098
|
+
const counts = fleetCounts(payload);
|
|
32099
|
+
const expected = asFiniteNumber(payload.expected) ?? FLEET_COUNT_KEYS.reduce((sum, key) => sum + counts[key], 0);
|
|
32100
|
+
const line = `settled ${counts.settled}/${expected} \xB7 rate_limited ${counts.rate_limited} \xB7 blocked ${counts.blocked}`;
|
|
32101
|
+
if (interactive) {
|
|
32102
|
+
process.stderr.write(`\r\x1B[2K${line}`);
|
|
32103
|
+
wrote = true;
|
|
32104
|
+
return;
|
|
32105
|
+
}
|
|
32106
|
+
const now = Date.now();
|
|
32107
|
+
if (wrote && now - lastPlainAt < FLEET_PLAIN_PROGRESS_INTERVAL_MS) return;
|
|
32108
|
+
lastPlainAt = now;
|
|
32109
|
+
wrote = true;
|
|
32110
|
+
process.stderr.write(`${line}
|
|
32111
|
+
`);
|
|
32112
|
+
},
|
|
32113
|
+
finish: () => {
|
|
32114
|
+
if (interactive && wrote) process.stderr.write("\n");
|
|
32115
|
+
}
|
|
32116
|
+
};
|
|
32117
|
+
}
|
|
32118
|
+
function fleetPlanLine(payload) {
|
|
32119
|
+
const plan = asRecord2(payload.plan) ?? {};
|
|
32120
|
+
const blocked = asRecord2(plan.blocked) ?? {};
|
|
32121
|
+
const entries = Object.entries(blocked).flatMap(([limitId, raw]) => {
|
|
32122
|
+
const count = asFiniteNumber(raw);
|
|
32123
|
+
return count === void 0 ? [] : [[limitId, count]];
|
|
32124
|
+
}).sort(([left], [right]) => left.localeCompare(right));
|
|
32125
|
+
const blockedTotal = entries.reduce((sum, [, count]) => sum + count, 0);
|
|
32126
|
+
const detail = entries.length === 0 ? "" : entries.length === 1 ? ` (${entries[0][0]})` : ` (${entries.map(([id, count]) => `${id}: ${count}`).join(", ")})`;
|
|
32127
|
+
return [
|
|
32128
|
+
`creates ${asFiniteNumber(plan.creates) ?? 0}`,
|
|
32129
|
+
`updates ${asFiniteNumber(plan.updates) ?? 0}`,
|
|
32130
|
+
`removes ${asFiniteNumber(plan.removes) ?? 0}`,
|
|
32131
|
+
`blocked ${blockedTotal}${detail}`
|
|
32132
|
+
].join(" \xB7 ");
|
|
32133
|
+
}
|
|
32134
|
+
function fleetCountsLine(payload) {
|
|
32135
|
+
const counts = fleetCounts(payload);
|
|
32136
|
+
return FLEET_COUNT_KEYS.map((key) => `${key} ${counts[key]}`).join(" \xB7 ");
|
|
32137
|
+
}
|
|
32138
|
+
function renderFleetSync(payload, input2) {
|
|
32139
|
+
const lines = [
|
|
32140
|
+
input2.dryRun ? `Fleet ${input2.fleetId} \u2014 plan only, nothing changed` : `Fleet ${input2.fleetId} \u2014 accepted`,
|
|
32141
|
+
` plan ${fleetPlanLine(payload)}`
|
|
32142
|
+
];
|
|
32143
|
+
const credits = asFiniteNumber(payload.credits_due_now);
|
|
32144
|
+
lines.push(` credits due now ${credits ?? 0}`);
|
|
32145
|
+
lines.push(
|
|
32146
|
+
` generation ${asFiniteNumber(payload.generation) ?? "unknown"} \xB7 replayed ${yesNo(
|
|
32147
|
+
payload.replayed
|
|
32148
|
+
)} \xB7 idempotency key ${input2.idempotencyKey}`
|
|
32149
|
+
);
|
|
32150
|
+
const next = fleetServerNext(payload);
|
|
32151
|
+
if (next) lines.push(`Next: ${next}`);
|
|
32152
|
+
return `${lines.join("\n")}
|
|
32153
|
+
`;
|
|
32154
|
+
}
|
|
32155
|
+
function renderFleetGet(payload) {
|
|
32156
|
+
const id = asString(payload.id) ?? "unknown";
|
|
32157
|
+
const status = fleetStatus(payload) ?? "unknown";
|
|
32158
|
+
const lines = [
|
|
32159
|
+
`Fleet ${id} \u2014 ${status}`,
|
|
32160
|
+
` monitors ${asFiniteNumber(payload.live) ?? 0} live / ${asFiniteNumber(payload.expected) ?? 0} expected`,
|
|
32161
|
+
` counts ${fleetCountsLine(payload)}`,
|
|
32162
|
+
` generation ${asFiniteNumber(payload.generation) ?? "unknown"} \xB7 converged generation ${asFiniteNumber(payload.converged_generation) ?? "none"}`
|
|
32163
|
+
];
|
|
32164
|
+
lines.push(...renderFleetDriftRows(payload));
|
|
32165
|
+
const next = fleetServerNext(payload) ?? (status === "degraded" ? `deepline monitors fleets get ${fleetShellArg(id)} --drift` : void 0);
|
|
32166
|
+
if (next) lines.push(`Next: ${next}`);
|
|
32167
|
+
return `${lines.join("\n")}
|
|
32168
|
+
`;
|
|
32169
|
+
}
|
|
32170
|
+
function renderFleetDriftRows(payload) {
|
|
32171
|
+
const drift = Array.isArray(payload.drift) ? payload.drift : void 0;
|
|
32172
|
+
if (!drift) return [];
|
|
32173
|
+
const rows = drift.flatMap((raw) => {
|
|
32174
|
+
const row = asRecord2(raw);
|
|
32175
|
+
return row ? [row] : [];
|
|
32176
|
+
}).map((row) => ({
|
|
32177
|
+
monitorKey: asString(row.monitor_key) ?? "-",
|
|
32178
|
+
entityKey: asString(row.entity_key) ?? "-",
|
|
32179
|
+
convergence: asString(row.convergence) ?? "-",
|
|
32180
|
+
since: asString(row.since) ?? "-",
|
|
32181
|
+
detail: asString(row.error) ?? (asString(row.blocked_by) ? `blocked_by ${asString(row.blocked_by)}` : asString(row.next_attempt_at) ? `next_attempt_at ${asString(row.next_attempt_at)}` : "")
|
|
32182
|
+
})).sort(
|
|
32183
|
+
(left, right) => left.monitorKey.localeCompare(right.monitorKey) || left.entityKey.localeCompare(right.entityKey)
|
|
32184
|
+
);
|
|
32185
|
+
if (rows.length === 0) {
|
|
32186
|
+
return [` drift none${payload.truncated === true ? " (truncated)" : ""}`];
|
|
32187
|
+
}
|
|
32188
|
+
const width = (values) => values.reduce((max, value) => Math.max(max, value.length), 0);
|
|
32189
|
+
const monitorWidth = width(rows.map((row) => row.monitorKey));
|
|
32190
|
+
const entityWidth = width(rows.map((row) => row.entityKey));
|
|
32191
|
+
const convergenceWidth = width(rows.map((row) => row.convergence));
|
|
32192
|
+
const lines = [
|
|
32193
|
+
` drift (${rows.length}${payload.truncated === true ? ", truncated" : ""})`
|
|
32194
|
+
];
|
|
32195
|
+
for (const row of rows) {
|
|
32196
|
+
lines.push(
|
|
32197
|
+
` ${row.monitorKey.padEnd(monitorWidth)} ${row.entityKey.padEnd(
|
|
32198
|
+
entityWidth
|
|
32199
|
+
)} ${row.convergence.padEnd(convergenceWidth)} ${row.since}${row.detail ? ` ${row.detail}` : ""}`
|
|
32200
|
+
);
|
|
32201
|
+
}
|
|
32202
|
+
return lines;
|
|
32203
|
+
}
|
|
32204
|
+
function renderFleetList(payload) {
|
|
32205
|
+
const fleets = (Array.isArray(payload.fleets) ? payload.fleets : []).flatMap((raw) => {
|
|
32206
|
+
const fleet = asRecord2(raw);
|
|
32207
|
+
return fleet ? [fleet] : [];
|
|
32208
|
+
}).sort(
|
|
32209
|
+
(left, right) => (asString(left.id) ?? "").localeCompare(asString(right.id) ?? "")
|
|
32210
|
+
);
|
|
32211
|
+
if (fleets.length === 0) {
|
|
32212
|
+
return "No Monitor Fleets in this workspace.\nNext: deepline monitors fleets init <fleet-id> --help\n";
|
|
32213
|
+
}
|
|
32214
|
+
const idWidth = fleets.reduce(
|
|
32215
|
+
(max, fleet) => Math.max(max, (asString(fleet.id) ?? "").length),
|
|
32216
|
+
0
|
|
32217
|
+
);
|
|
32218
|
+
const statusWidth = fleets.reduce(
|
|
32219
|
+
(max, fleet) => Math.max(max, (fleetStatus(fleet) ?? "unknown").length),
|
|
32220
|
+
0
|
|
32221
|
+
);
|
|
32222
|
+
const lines = [`Fleets (${fleets.length})`];
|
|
32223
|
+
for (const fleet of fleets) {
|
|
32224
|
+
const counts = fleetCounts(fleet);
|
|
32225
|
+
const trouble = [
|
|
32226
|
+
counts.blocked ? `blocked ${counts.blocked}` : "",
|
|
32227
|
+
counts.failed ? `failed ${counts.failed}` : ""
|
|
32228
|
+
].filter(Boolean);
|
|
32229
|
+
lines.push(
|
|
32230
|
+
` ${(asString(fleet.id) ?? "-").padEnd(idWidth)} ${(fleetStatus(fleet) ?? "unknown").padEnd(statusWidth)} ${asFiniteNumber(fleet.live) ?? 0}/${asFiniteNumber(fleet.expected) ?? 0}${trouble.length ? ` ${trouble.join(" \xB7 ")}` : ""}`
|
|
32231
|
+
);
|
|
32232
|
+
}
|
|
32233
|
+
return `${lines.join("\n")}
|
|
32234
|
+
`;
|
|
32235
|
+
}
|
|
32236
|
+
function renderFleetDeactivatePlan(payload, fleetId) {
|
|
32237
|
+
const radius = asRecord2(payload.would_deactivate) ?? {};
|
|
32238
|
+
const lines = [
|
|
32239
|
+
`Deactivate fleet ${fleetId} \u2014 plan only, nothing changed`,
|
|
32240
|
+
` would deactivate ${asFiniteNumber(radius.monitors) ?? 0} monitors \xB7 ${asFiniteNumber(radius.accounts) ?? 0} accounts`
|
|
32241
|
+
];
|
|
32242
|
+
const note = asString(payload.note);
|
|
32243
|
+
if (note) lines.push(` ${note}`);
|
|
32244
|
+
lines.push(
|
|
32245
|
+
`Next: ${fleetServerNext(payload) ?? `deepline monitors fleets deactivate ${fleetShellArg(fleetId)} --yes`}`
|
|
32246
|
+
);
|
|
32247
|
+
return `${lines.join("\n")}
|
|
32248
|
+
`;
|
|
32249
|
+
}
|
|
32250
|
+
function reportFleetState(payload, error, options) {
|
|
32251
|
+
printCommandEnvelope(
|
|
32252
|
+
{
|
|
32253
|
+
...payload,
|
|
32254
|
+
code: error.code,
|
|
32255
|
+
message: error.message,
|
|
32256
|
+
next: error.next
|
|
32257
|
+
},
|
|
32258
|
+
{
|
|
32259
|
+
json: options.json,
|
|
32260
|
+
text: `${options.text}${error.message}
|
|
32261
|
+
Next: ${error.next}
|
|
32262
|
+
`
|
|
32263
|
+
}
|
|
32264
|
+
);
|
|
32265
|
+
process.exitCode = monitorsErrorExitCode(error);
|
|
32266
|
+
}
|
|
32267
|
+
function fleetSourceTable(value) {
|
|
32268
|
+
const [schema, table, extra] = value?.trim().split(".") ?? [];
|
|
32269
|
+
if (!schema || !table || extra || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(schema) || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(table)) {
|
|
32270
|
+
throw new MonitorsUsageError(
|
|
32271
|
+
"--source must be a Customer DB table in schema.table form."
|
|
32272
|
+
);
|
|
32273
|
+
}
|
|
32274
|
+
return { schema, table };
|
|
32275
|
+
}
|
|
32276
|
+
function fleetColumnName(value, flag) {
|
|
32277
|
+
const name = value?.trim();
|
|
32278
|
+
if (!name || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
|
|
32279
|
+
throw new MonitorsUsageError(`${flag} must be a SQL column identifier.`);
|
|
32280
|
+
}
|
|
32281
|
+
return name;
|
|
32282
|
+
}
|
|
32283
|
+
function fleetMemberLimit(value) {
|
|
32284
|
+
if (value === void 0) return 1e3;
|
|
32285
|
+
const limit = fleetIntegerOption(value, "--limit");
|
|
32286
|
+
if (!limit || limit > 1e3) {
|
|
32287
|
+
throw new MonitorsUsageError("--limit must be between 1 and 1,000.");
|
|
32288
|
+
}
|
|
32289
|
+
return limit;
|
|
32290
|
+
}
|
|
32291
|
+
function fleetOrderBy(values, sourceKey) {
|
|
32292
|
+
const parsed = (values ?? []).map((value) => {
|
|
32293
|
+
const match = /^([A-Za-z_][A-Za-z0-9_]*):(asc|desc)$/.exec(value.trim());
|
|
32294
|
+
if (!match) {
|
|
32295
|
+
throw new MonitorsUsageError(
|
|
32296
|
+
"--order-by must use column:asc or column:desc."
|
|
32297
|
+
);
|
|
32298
|
+
}
|
|
32299
|
+
return { column: match[1], direction: match[2] };
|
|
32300
|
+
});
|
|
32301
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32302
|
+
for (const order of parsed) {
|
|
32303
|
+
if (seen.has(order.column)) {
|
|
32304
|
+
throw new MonitorsUsageError(
|
|
32305
|
+
`--order-by repeats '${order.column}'. Each column may appear once.`
|
|
32306
|
+
);
|
|
32307
|
+
}
|
|
32308
|
+
seen.add(order.column);
|
|
32309
|
+
}
|
|
32310
|
+
const sourceOrder = parsed.find((order) => order.column === sourceKey);
|
|
32311
|
+
return [
|
|
32312
|
+
...parsed.filter((order) => order.column !== sourceKey),
|
|
32313
|
+
sourceOrder ?? { column: sourceKey, direction: "asc" }
|
|
32314
|
+
];
|
|
32315
|
+
}
|
|
32316
|
+
async function handleMonitorFleetsInit(fleetId, options) {
|
|
32317
|
+
if (!/^[a-z][a-z0-9-]{0,199}$/.test(fleetId)) {
|
|
32318
|
+
throw new MonitorsUsageError("<fleet-id> must be lowercase kebab-case.");
|
|
32319
|
+
}
|
|
32320
|
+
const source = fleetSourceTable(options.source);
|
|
32321
|
+
const key = fleetColumnName(options.key, "--key");
|
|
32322
|
+
const keyType = options.keyType?.trim() ?? "text";
|
|
32323
|
+
if (!["text", "uuid", "int4", "int8"].includes(keyType)) {
|
|
32324
|
+
throw new MonitorsUsageError(
|
|
32325
|
+
"--key-type must be text, uuid, int4, or int8."
|
|
32326
|
+
);
|
|
32327
|
+
}
|
|
32328
|
+
const tool = options.tool?.trim();
|
|
32329
|
+
if (!tool) throw new MonitorsUsageError("--tool is required.");
|
|
32330
|
+
if (!options.payload) {
|
|
32331
|
+
throw new MonitorsUsageError(
|
|
32332
|
+
"--payload is required and must be the monitor payload JSON for --tool."
|
|
32333
|
+
);
|
|
32334
|
+
}
|
|
32335
|
+
const payload = parseJsonObjectArg(options.payload, "--payload");
|
|
32336
|
+
const where = options.where ? parseJsonObjectArg(options.where, "--where") : void 0;
|
|
32337
|
+
const out = options.out?.trim();
|
|
32338
|
+
if (!out) throw new MonitorsUsageError("--out is required.");
|
|
32339
|
+
const authoredDefinition = {
|
|
32340
|
+
id: fleetId,
|
|
32341
|
+
source: {
|
|
32342
|
+
kind: "customer_db_table",
|
|
32343
|
+
schema: source.schema,
|
|
32344
|
+
table: source.table,
|
|
32345
|
+
key: { column: key, type: keyType },
|
|
32346
|
+
...where ? { where } : {}
|
|
32347
|
+
},
|
|
32348
|
+
member: {
|
|
32349
|
+
tool,
|
|
32350
|
+
key: {
|
|
32351
|
+
$fleet: "template",
|
|
32352
|
+
parts: [`${fleetId}-`, { $fleet: "column", name: key }]
|
|
32353
|
+
},
|
|
32354
|
+
payload
|
|
32355
|
+
},
|
|
32356
|
+
selection: {
|
|
32357
|
+
limit: fleetMemberLimit(options.limit),
|
|
32358
|
+
orderBy: fleetOrderBy(options.orderBy, key),
|
|
32359
|
+
membership: "sticky"
|
|
32360
|
+
}
|
|
32361
|
+
};
|
|
32362
|
+
const definition = requireCompiledFleetDefinition(authoredDefinition);
|
|
32363
|
+
const file = resolve14(out);
|
|
32364
|
+
writeFileSync12(file, `${JSON.stringify(definition, null, 2)}
|
|
32365
|
+
`, "utf8");
|
|
32366
|
+
const next = `deepline monitors fleets sync --file ${fleetShellArg(file)} --dry-run --json`;
|
|
32367
|
+
printCommandEnvelope(
|
|
32368
|
+
{ schemaVersion: 1, file, definition, next },
|
|
32369
|
+
{
|
|
32370
|
+
json: options.json,
|
|
32371
|
+
text: `Wrote ${file}
|
|
32372
|
+
Next: ${next}
|
|
32373
|
+
`
|
|
32374
|
+
}
|
|
32375
|
+
);
|
|
32376
|
+
}
|
|
32377
|
+
function requireCompiledFleetDefinition(definition) {
|
|
32378
|
+
const result = admitMonitorFleetAuthoringContract(definition);
|
|
32379
|
+
if (result.valid && result.contract) return result.contract.definition;
|
|
32380
|
+
const messages = result.issues.map((issue) => `${issue.path || "definition"}: ${issue.message}`).join("; ");
|
|
32381
|
+
throw new MonitorsUsageError(
|
|
32382
|
+
`Monitor Fleet definition failed local contract check. ${messages}
|
|
32383
|
+
Fix the file, then re-run: deepline monitors fleets sync --file <fleet.json> --dry-run`
|
|
32384
|
+
);
|
|
32385
|
+
}
|
|
32386
|
+
function fleetSyncCommandLine(target, options) {
|
|
32387
|
+
const parts = ["deepline monitors fleets sync"];
|
|
32388
|
+
if (options.file) parts.push(`--file ${fleetShellArg(options.file)}`);
|
|
32389
|
+
else if (target) parts.push(fleetShellArg(target));
|
|
32390
|
+
if (options.dryRun) parts.push("--dry-run");
|
|
32391
|
+
if (options.wait) parts.push("--wait");
|
|
32392
|
+
if (options.timeout)
|
|
32393
|
+
parts.push(`--timeout ${fleetShellArg(options.timeout)}`);
|
|
32394
|
+
if (options.expectedGeneration !== void 0) {
|
|
32395
|
+
parts.push(
|
|
32396
|
+
`--expected-generation ${fleetShellArg(options.expectedGeneration)}`
|
|
32397
|
+
);
|
|
32398
|
+
}
|
|
32399
|
+
if (options.idempotencyKey) {
|
|
32400
|
+
parts.push(`--idempotency-key ${fleetShellArg(options.idempotencyKey)}`);
|
|
32401
|
+
}
|
|
32402
|
+
parts.push(...fleetJsonFlag(options));
|
|
32403
|
+
return parts.join(" ");
|
|
32404
|
+
}
|
|
32405
|
+
async function handleMonitorFleetsSync(target, options, idempotencyKey) {
|
|
32406
|
+
const usesDefinition = options.file !== void 0 || target?.trim().startsWith("{") === true;
|
|
32407
|
+
if (!usesDefinition && !target?.trim()) {
|
|
32408
|
+
throw new MonitorsUsageError(
|
|
32409
|
+
"sync needs a fleet: pass --file fleet.json to apply a definition, or <fleet-id> to re-plan the stored one.\n deepline monitors fleets sync --file fleet.json --dry-run\n deepline monitors fleets sync <fleet-id> --dry-run"
|
|
32410
|
+
);
|
|
32411
|
+
}
|
|
32412
|
+
const definition = usesDefinition ? requireCompiledFleetDefinition(
|
|
32413
|
+
resolveMonitorJsonBody({
|
|
32414
|
+
positional: target,
|
|
32415
|
+
file: options.file,
|
|
32416
|
+
argLabel: "<definition>",
|
|
32417
|
+
command: "deepline monitors fleets sync"
|
|
32418
|
+
})
|
|
32419
|
+
) : void 0;
|
|
32420
|
+
const fleetId = definition ? asString(definition.id) ?? "" : target.trim();
|
|
32421
|
+
if (!fleetId) {
|
|
32422
|
+
throw new MonitorsUsageError(
|
|
32423
|
+
'The Fleet definition has no id. Add a top-level "id" and re-run.'
|
|
32424
|
+
);
|
|
32425
|
+
}
|
|
32426
|
+
const client2 = new DeeplineClient();
|
|
32427
|
+
const payload = await client2.monitors.fleets.sync(
|
|
32428
|
+
definition ?? fleetId,
|
|
32429
|
+
{
|
|
32430
|
+
...options.dryRun ? { dryRun: true } : {},
|
|
32431
|
+
...options.expectedGeneration !== void 0 ? {
|
|
32432
|
+
expectedGeneration: fleetIntegerOption(
|
|
32433
|
+
options.expectedGeneration,
|
|
32434
|
+
"--expected-generation"
|
|
32435
|
+
)
|
|
32436
|
+
} : {},
|
|
32437
|
+
idempotencyKey
|
|
32438
|
+
}
|
|
32439
|
+
);
|
|
32440
|
+
if (options.dryRun) {
|
|
32441
|
+
assertMonitorDryRunAcknowledged(payload, {
|
|
32442
|
+
command: "deepline monitors fleets sync",
|
|
32443
|
+
mutation: "fleet sync"
|
|
32444
|
+
});
|
|
32445
|
+
}
|
|
32446
|
+
const accepted = { ...payload, idempotency_key: idempotencyKey };
|
|
32447
|
+
if (!options.wait || options.dryRun) {
|
|
32448
|
+
printCommandEnvelope(accepted, {
|
|
32449
|
+
json: options.json,
|
|
32450
|
+
text: renderFleetSync(payload, {
|
|
32451
|
+
fleetId,
|
|
32452
|
+
dryRun: options.dryRun === true,
|
|
32453
|
+
idempotencyKey
|
|
32454
|
+
})
|
|
32455
|
+
});
|
|
32456
|
+
return;
|
|
32457
|
+
}
|
|
32458
|
+
const timeoutMs = fleetTimeoutMs(options.timeout);
|
|
32459
|
+
const progress = fleetProgressReporter();
|
|
32460
|
+
let final;
|
|
32461
|
+
try {
|
|
32462
|
+
final = await client2.monitors.fleets.waitForConvergence(fleetId, {
|
|
32463
|
+
timeoutMs,
|
|
32464
|
+
pollIntervalMs: FLEET_POLL_INTERVAL_MS,
|
|
32465
|
+
onProgress: progress.report
|
|
32466
|
+
});
|
|
32467
|
+
} finally {
|
|
32468
|
+
progress.finish();
|
|
32469
|
+
}
|
|
32470
|
+
const envelope = { ...accepted, ...final };
|
|
32471
|
+
const status = fleetStatus(final);
|
|
32472
|
+
const summary = renderFleetGet(final);
|
|
32473
|
+
if (status === "converged") {
|
|
32474
|
+
printCommandEnvelope(envelope, { json: options.json, text: summary });
|
|
32475
|
+
return;
|
|
32476
|
+
}
|
|
32477
|
+
const driftCommand = `deepline monitors fleets get ${fleetShellArg(fleetId)} --drift --json`;
|
|
32478
|
+
if (status === "degraded") {
|
|
32479
|
+
reportFleetState(
|
|
32480
|
+
envelope,
|
|
32481
|
+
new MonitorFleetStateError({
|
|
32482
|
+
code: "MONITOR_FLEET_DEGRADED",
|
|
32483
|
+
message: `Fleet ${fleetId} is degraded: some members will not converge without a change. Retrying sync will not fix it.`,
|
|
32484
|
+
next: fleetServerNext(final) ?? driftCommand
|
|
32485
|
+
}),
|
|
32486
|
+
{ json: options.json, text: summary }
|
|
32487
|
+
);
|
|
32488
|
+
return;
|
|
32489
|
+
}
|
|
32490
|
+
reportFleetState(
|
|
32491
|
+
envelope,
|
|
32492
|
+
new MonitorFleetStateError({
|
|
32493
|
+
code: "MONITOR_FLEET_WAIT_TIMEOUT",
|
|
32494
|
+
message: `Stopped waiting after ${timeoutMs}ms. Nothing is broken and nothing was lost \u2014 fleet ${fleetId} is still ${status ?? "working"} on the server.`,
|
|
32495
|
+
next: fleetServerNext(final) ?? driftCommand
|
|
32496
|
+
}),
|
|
32497
|
+
{ json: options.json, text: summary }
|
|
32498
|
+
);
|
|
32499
|
+
}
|
|
32500
|
+
async function handleMonitorFleetsGet(fleetId, options) {
|
|
32501
|
+
if (options.drift && !fleetId) {
|
|
32502
|
+
throw new MonitorsUsageError(
|
|
32503
|
+
"--drift needs a fleet id: deepline monitors fleets get <fleet-id> --drift"
|
|
32504
|
+
);
|
|
32505
|
+
}
|
|
32506
|
+
const limit = options.limit === void 0 ? void 0 : fleetIntegerOption(options.limit, "--limit");
|
|
32507
|
+
const client2 = new DeeplineClient();
|
|
32508
|
+
const payload = await client2.monitors.fleets.get(fleetId, {
|
|
32509
|
+
...options.drift ? { drift: true } : {},
|
|
32510
|
+
...limit !== void 0 ? { limit } : {}
|
|
32511
|
+
});
|
|
32512
|
+
const text = fleetId ? renderFleetGet(payload) : renderFleetList(payload);
|
|
32513
|
+
if (!options.check) {
|
|
32514
|
+
printCommandEnvelope(payload, { json: options.json, text });
|
|
32515
|
+
return;
|
|
32516
|
+
}
|
|
32517
|
+
const statuses = fleetId ? [fleetStatus(payload)] : (Array.isArray(payload.fleets) ? payload.fleets : []).map(
|
|
32518
|
+
(raw) => fleetStatus(asRecord2(raw) ?? {})
|
|
32519
|
+
);
|
|
32520
|
+
const unconverged = statuses.filter((status) => status !== "converged");
|
|
32521
|
+
if (unconverged.length === 0) {
|
|
32522
|
+
printCommandEnvelope(payload, { json: options.json, text });
|
|
32523
|
+
return;
|
|
32524
|
+
}
|
|
32525
|
+
const target = fleetId ?? "<fleet-id>";
|
|
32526
|
+
const degraded = unconverged.includes("degraded");
|
|
32527
|
+
reportFleetState(
|
|
32528
|
+
payload,
|
|
32529
|
+
new MonitorFleetStateError({
|
|
32530
|
+
code: degraded ? "MONITOR_FLEET_DEGRADED" : "MONITOR_FLEET_NOT_CONVERGED",
|
|
32531
|
+
message: degraded ? `Fleet ${target} is degraded: members are stuck and retrying will not move them.` : `Fleet ${target} has not converged yet.`,
|
|
32532
|
+
next: fleetServerNext(payload) ?? `deepline monitors fleets get ${fleetShellArg(target)} --drift --json`
|
|
32533
|
+
}),
|
|
32534
|
+
{ json: options.json, text }
|
|
32535
|
+
);
|
|
32536
|
+
}
|
|
32537
|
+
function fleetDeactivateCommandLine(fleetId, options) {
|
|
32538
|
+
const parts = [
|
|
32539
|
+
"deepline monitors fleets deactivate",
|
|
32540
|
+
fleetShellArg(fleetId),
|
|
32541
|
+
"--yes"
|
|
32542
|
+
];
|
|
32543
|
+
if (options.dryRun) parts.push("--dry-run");
|
|
32544
|
+
if (options.wait) parts.push("--wait");
|
|
32545
|
+
if (options.timeout)
|
|
32546
|
+
parts.push(`--timeout ${fleetShellArg(options.timeout)}`);
|
|
32547
|
+
if (options.idempotencyKey) {
|
|
32548
|
+
parts.push(`--idempotency-key ${fleetShellArg(options.idempotencyKey)}`);
|
|
32549
|
+
}
|
|
32550
|
+
parts.push(...fleetJsonFlag(options));
|
|
32551
|
+
return parts.join(" ");
|
|
32552
|
+
}
|
|
32553
|
+
async function confirmFleetDeactivate(fleetId, plan) {
|
|
32554
|
+
process.stderr.write(renderFleetDeactivatePlan(plan, fleetId));
|
|
32555
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
32556
|
+
try {
|
|
32557
|
+
const answer = await rl.question(
|
|
32558
|
+
`Deactivate fleet "${fleetId}" and the monitors it owns? [y/N] `
|
|
32559
|
+
);
|
|
32560
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
32561
|
+
} finally {
|
|
32562
|
+
rl.close();
|
|
32563
|
+
}
|
|
32564
|
+
}
|
|
32565
|
+
async function handleMonitorFleetsDeactivate(fleetId, options, idempotencyKey) {
|
|
32566
|
+
const client2 = new DeeplineClient();
|
|
32567
|
+
if (options.dryRun) {
|
|
32568
|
+
const plan = await client2.monitors.fleets.deactivate(fleetId, {
|
|
32569
|
+
dryRun: true,
|
|
32570
|
+
idempotencyKey
|
|
32571
|
+
});
|
|
32572
|
+
assertMonitorDryRunAcknowledged(plan, {
|
|
32573
|
+
command: "deepline monitors fleets deactivate",
|
|
32574
|
+
mutation: "fleet deactivate"
|
|
32575
|
+
});
|
|
32576
|
+
printCommandEnvelope(plan, {
|
|
32577
|
+
json: options.json,
|
|
32578
|
+
text: renderFleetDeactivatePlan(plan, fleetId)
|
|
32579
|
+
});
|
|
32580
|
+
return;
|
|
32581
|
+
}
|
|
32582
|
+
if (!options.yes) {
|
|
32583
|
+
const interactive = process.stdout.isTTY === true && process.stdin.isTTY === true;
|
|
32584
|
+
if (!interactive) {
|
|
32585
|
+
throw new MonitorsUsageError(
|
|
32586
|
+
`deactivate is destructive: it deactivates fleet "${fleetId}" and every monitor it owns. Non-interactive runs must confirm with --yes:
|
|
32587
|
+
${fleetDeactivateCommandLine(fleetId, options)}
|
|
32588
|
+
Preview the blast radius first:
|
|
32589
|
+
deepline monitors fleets deactivate ${fleetShellArg(fleetId)} --dry-run`
|
|
32590
|
+
);
|
|
32591
|
+
}
|
|
32592
|
+
const plan = await client2.monitors.fleets.deactivate(fleetId, {
|
|
32593
|
+
dryRun: true,
|
|
32594
|
+
idempotencyKey: `${idempotencyKey}-plan`
|
|
32595
|
+
});
|
|
32596
|
+
assertMonitorDryRunAcknowledged(plan, {
|
|
32597
|
+
command: "deepline monitors fleets deactivate",
|
|
32598
|
+
mutation: "fleet deactivate"
|
|
32599
|
+
});
|
|
32600
|
+
if (!await confirmFleetDeactivate(fleetId, plan)) {
|
|
32601
|
+
process.stderr.write(
|
|
32602
|
+
`Aborted. Fleet "${fleetId}" was not deactivated.
|
|
32603
|
+
`
|
|
32604
|
+
);
|
|
32605
|
+
process.exitCode = 2;
|
|
32606
|
+
return;
|
|
32607
|
+
}
|
|
32608
|
+
}
|
|
32609
|
+
const payload = await client2.monitors.fleets.deactivate(fleetId, {
|
|
32610
|
+
idempotencyKey
|
|
32611
|
+
});
|
|
32612
|
+
const accepted = { ...payload, idempotency_key: idempotencyKey };
|
|
32613
|
+
if (payload.already === true) {
|
|
32614
|
+
printCommandEnvelope(accepted, {
|
|
32615
|
+
json: options.json,
|
|
32616
|
+
text: `Fleet ${fleetId} is already deactivated.
|
|
32617
|
+
`
|
|
32618
|
+
});
|
|
32619
|
+
return;
|
|
32620
|
+
}
|
|
32621
|
+
const acceptedText = `Fleet ${fleetId} \u2014 ${asString(payload.status) ?? "deactivating"}
|
|
32622
|
+
idempotency key ${idempotencyKey}
|
|
32623
|
+
` + (fleetServerNext(payload) ? `Next: ${fleetServerNext(payload)}
|
|
32624
|
+
` : "");
|
|
32625
|
+
if (!options.wait) {
|
|
32626
|
+
printCommandEnvelope(accepted, {
|
|
32627
|
+
json: options.json,
|
|
32628
|
+
text: acceptedText
|
|
32629
|
+
});
|
|
32630
|
+
return;
|
|
32631
|
+
}
|
|
32632
|
+
const timeoutMs = fleetTimeoutMs(options.timeout);
|
|
32633
|
+
const progress = fleetProgressReporter();
|
|
32634
|
+
let final;
|
|
32635
|
+
try {
|
|
32636
|
+
final = await client2.monitors.fleets.waitForConvergence(fleetId, {
|
|
32637
|
+
timeoutMs,
|
|
32638
|
+
pollIntervalMs: FLEET_POLL_INTERVAL_MS,
|
|
32639
|
+
onProgress: progress.report,
|
|
32640
|
+
until: "deactivated"
|
|
32641
|
+
});
|
|
32642
|
+
} finally {
|
|
32643
|
+
progress.finish();
|
|
32644
|
+
}
|
|
32645
|
+
const envelope = { ...accepted, ...final };
|
|
32646
|
+
const summary = renderFleetGet(final);
|
|
32647
|
+
if (fleetStatus(final) === "deactivated") {
|
|
32648
|
+
printCommandEnvelope(envelope, { json: options.json, text: summary });
|
|
32649
|
+
return;
|
|
32650
|
+
}
|
|
32651
|
+
reportFleetState(
|
|
32652
|
+
envelope,
|
|
32653
|
+
new MonitorFleetStateError({
|
|
32654
|
+
code: "MONITOR_FLEET_WAIT_TIMEOUT",
|
|
32655
|
+
message: `Stopped waiting after ${timeoutMs}ms. Deactivation of fleet ${fleetId} is still in progress on the server; nothing was lost.`,
|
|
32656
|
+
next: fleetServerNext(final) ?? `deepline monitors fleets get ${fleetShellArg(fleetId)} --json`
|
|
32657
|
+
}),
|
|
32658
|
+
{ json: options.json, text: summary }
|
|
32659
|
+
);
|
|
32660
|
+
}
|
|
32661
|
+
function handleMonitorFleetsOverview(options) {
|
|
32662
|
+
const lines = [
|
|
32663
|
+
"Monitor Fleets \u2014 one Customer DB table row, one ordinary monitor.",
|
|
32664
|
+
"",
|
|
32665
|
+
"Lifecycle:",
|
|
32666
|
+
...MONITOR_FLEET_LIFECYCLE.flatMap((entry) => [
|
|
32667
|
+
` ${entry.step}. ${entry.what}`,
|
|
32668
|
+
` ${entry.command}`
|
|
32669
|
+
]),
|
|
32670
|
+
"",
|
|
32671
|
+
"Commands:",
|
|
32672
|
+
...MONITOR_FLEET_COMMANDS.map(
|
|
32673
|
+
(command) => ` ${command.name.padEnd(12)}${command.summary}`
|
|
32674
|
+
),
|
|
32675
|
+
"",
|
|
32676
|
+
"Agent notes:",
|
|
32677
|
+
...MONITOR_FLEET_AGENT_NOTES.map((note) => ` ${note}`)
|
|
32678
|
+
];
|
|
32679
|
+
printCommandEnvelope(
|
|
32680
|
+
{
|
|
32681
|
+
schemaVersion: 1,
|
|
32682
|
+
lifecycle: MONITOR_FLEET_LIFECYCLE,
|
|
32683
|
+
commands: MONITOR_FLEET_COMMANDS,
|
|
32684
|
+
agent_notes: MONITOR_FLEET_AGENT_NOTES,
|
|
32685
|
+
next: MONITOR_FLEET_LIFECYCLE[0].command
|
|
32686
|
+
},
|
|
32687
|
+
{ json: options.json, text: `${lines.join("\n")}
|
|
32688
|
+
` }
|
|
32689
|
+
);
|
|
32690
|
+
}
|
|
31536
32691
|
function renderMonitorGet(payload) {
|
|
31537
32692
|
const key = asString(payload.key);
|
|
31538
32693
|
const tool = asString(payload.tool);
|
|
@@ -31782,7 +32937,9 @@ Notes:
|
|
|
31782
32937
|
|
|
31783
32938
|
Exit codes:
|
|
31784
32939
|
0 success; 2 usage/local input; 3 auth or permission; 4 not found;
|
|
31785
|
-
5 server failure;
|
|
32940
|
+
5 server failure (retry the same command); 6 not at the desired state
|
|
32941
|
+
(fleets: degraded, or --wait/--check stopped while healthy \u2014 retrying
|
|
32942
|
+
changes nothing); 7 refused, change the request.
|
|
31786
32943
|
\`monitors status\` exits 1 when you lack monitor access (documented contract).
|
|
31787
32944
|
|
|
31788
32945
|
Examples:
|
|
@@ -32053,6 +33210,181 @@ Examples:
|
|
|
32053
33210
|
`
|
|
32054
33211
|
).option("--dry-run", "Show the reactivation cost without reactivating")
|
|
32055
33212
|
).action(monitorsAction(handleMonitorsReactivate));
|
|
33213
|
+
const fleets = monitors.command("fleets").description("Define and reconcile table-backed Monitor Fleets.").addHelpText(
|
|
33214
|
+
"after",
|
|
33215
|
+
`
|
|
33216
|
+
Notes:
|
|
33217
|
+
A Monitor Fleet maps eligible rows in one Customer DB table to ordinary
|
|
33218
|
+
monitors. Fleet definitions are canonical JSON, and \`sync\` is the only verb
|
|
33219
|
+
that changes one: applying the same definition twice is the same operation,
|
|
33220
|
+
so the server answers \`replayed: true\` instead of building a second fleet.
|
|
33221
|
+
The fleet's status is computed by Deepline; this CLI reports it and never
|
|
33222
|
+
recomputes a verdict from the counts.
|
|
33223
|
+
|
|
33224
|
+
Exit codes:
|
|
33225
|
+
0 converged or done; 2 usage or local validation; 3 auth; 4 not found;
|
|
33226
|
+
5 server failure (retry the same command); 6 not at the desired state
|
|
33227
|
+
(degraded, or --wait/--check stopped while healthy); 7 refused (change the
|
|
33228
|
+
request).
|
|
33229
|
+
|
|
33230
|
+
Lifecycle:
|
|
33231
|
+
${MONITOR_FLEET_LIFECYCLE.map(
|
|
33232
|
+
(entry) => ` ${entry.step}. ${entry.command}`
|
|
33233
|
+
).join("\n")}
|
|
33234
|
+
${MONITOR_FLEET_HELP_EPILOG}`
|
|
33235
|
+
).action(
|
|
33236
|
+
monitorsAction(async (options) => {
|
|
33237
|
+
handleMonitorFleetsOverview(options);
|
|
33238
|
+
})
|
|
33239
|
+
);
|
|
33240
|
+
withJsonOption(fleets);
|
|
33241
|
+
withJsonOption(
|
|
33242
|
+
fleets.command("init <fleet-id>").description("Write an opinionated Fleet definition JSON file.").addHelpText(
|
|
33243
|
+
"after",
|
|
33244
|
+
`
|
|
33245
|
+
Creates a ready-to-review JSON definition. Fleets always sync ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.cadence} and retain
|
|
33246
|
+
a missing member for ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.removalGrace} before it is ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.onRemoved}d; those
|
|
33247
|
+
policies are not authored in the file. ${MONITOR_FLEET_DOCUMENTATION.stickyMembership} The payload remains the actual monitor payload for the chosen tool, so use
|
|
33248
|
+
\`deepline monitors available\` to discover a tool first.
|
|
33249
|
+
|
|
33250
|
+
Example:
|
|
33251
|
+
deepline monitors fleets init account-job-openings \\
|
|
33252
|
+
--source public.accounts --key account_id --key-type uuid \\
|
|
33253
|
+
--tool deepline_native.company_radar \\
|
|
33254
|
+
--payload '{"domain":{"$fleet":"column","name":"domain"},"radar_type":"company_job_openings"}' \\
|
|
33255
|
+
--order-by intent_score:desc \\
|
|
33256
|
+
--out fleet.json
|
|
33257
|
+
`
|
|
33258
|
+
).requiredOption("--source <schema.table>", "Customer DB source table").requiredOption("--key <column>", "Unique source-row key column").option("--key-type <type>", "text, uuid, int4, or int8 (default text)").requiredOption("--tool <tool>", "Monitor tool to create per source row").requiredOption(
|
|
33259
|
+
"--payload <json>",
|
|
33260
|
+
"Monitor payload JSON for --tool; use $fleet column tags for row values"
|
|
33261
|
+
).option(
|
|
33262
|
+
"--where <json>",
|
|
33263
|
+
"Optional source-row equality filter JSON; not arbitrary SQL"
|
|
33264
|
+
).option(
|
|
33265
|
+
"--order-by <column:direction>",
|
|
33266
|
+
"Rank candidates; repeatable, with the source key appended for stability",
|
|
33267
|
+
(value, previous = []) => [...previous, value],
|
|
33268
|
+
[]
|
|
33269
|
+
).option(
|
|
33270
|
+
"--limit <n>",
|
|
33271
|
+
"Maximum active members; ranking changes do not churn sticky members (default 1,000)"
|
|
33272
|
+
).requiredOption("--out <path>", "Write the definition JSON to this path")
|
|
33273
|
+
).action(monitorsAction(handleMonitorFleetsInit));
|
|
33274
|
+
withJsonOption(
|
|
33275
|
+
fleets.command("sync [fleet-id]").description(
|
|
33276
|
+
"Apply a Fleet definition, or re-plan an existing fleet from its stored one."
|
|
33277
|
+
).addHelpText(
|
|
33278
|
+
"after",
|
|
33279
|
+
`
|
|
33280
|
+
Notes:
|
|
33281
|
+
--file (or an inline definition, or --file - for stdin) is compiled locally
|
|
33282
|
+
BEFORE any network call: a definition that fails the contract exits 2 and
|
|
33283
|
+
never becomes a request. A bare <fleet-id> re-plans the stored definition.
|
|
33284
|
+
The plan always shows blocked members; they are never hidden.
|
|
33285
|
+
--wait polls until Deepline reports a terminal status: converged exits 0,
|
|
33286
|
+
degraded exits 6, and a timeout exits 6 without implying anything broke.
|
|
33287
|
+
Progress goes to stderr, so stdout stays exactly one JSON object.
|
|
33288
|
+
|
|
33289
|
+
Examples:
|
|
33290
|
+
deepline monitors fleets sync --file fleet.json --dry-run
|
|
33291
|
+
deepline monitors fleets sync --file fleet.json --wait --timeout 20m
|
|
33292
|
+
deepline monitors fleets sync account-job-openings --wait --json
|
|
33293
|
+
cat fleet.json | deepline monitors fleets sync --file - --dry-run --json
|
|
33294
|
+
`
|
|
33295
|
+
).option(
|
|
33296
|
+
"-f, --file <path>",
|
|
33297
|
+
"Apply definition JSON from a file, or - for stdin"
|
|
33298
|
+
).option(
|
|
33299
|
+
"--dry-run",
|
|
33300
|
+
"Show the plan and the credits due without changing state"
|
|
33301
|
+
).option("--wait", "Poll until the fleet reaches a terminal status").option(
|
|
33302
|
+
"--timeout <duration>",
|
|
33303
|
+
"How long --wait may poll: 500ms, 90s, 10m, 1h (default 10m)"
|
|
33304
|
+
).option(
|
|
33305
|
+
"--expected-generation <generation>",
|
|
33306
|
+
"Refuse the write unless the fleet is at this generation"
|
|
33307
|
+
).option(
|
|
33308
|
+
"--idempotency-key <key>",
|
|
33309
|
+
"Stable retry key (generated and returned when omitted)"
|
|
33310
|
+
)
|
|
33311
|
+
).action(async (target, options) => {
|
|
33312
|
+
let retryCommand = fleetSyncCommandLine(target, options);
|
|
33313
|
+
try {
|
|
33314
|
+
const idempotencyKey = fleetIdempotencyKey(
|
|
33315
|
+
"sync",
|
|
33316
|
+
options.idempotencyKey
|
|
33317
|
+
);
|
|
33318
|
+
retryCommand = fleetSyncCommandLine(target, {
|
|
33319
|
+
...options,
|
|
33320
|
+
idempotencyKey
|
|
33321
|
+
});
|
|
33322
|
+
await handleMonitorFleetsSync(target, options, idempotencyKey);
|
|
33323
|
+
} catch (error) {
|
|
33324
|
+
reportMonitorsFailure(error, { retryCommand });
|
|
33325
|
+
}
|
|
33326
|
+
});
|
|
33327
|
+
withJsonOption(
|
|
33328
|
+
fleets.command("get [fleet-id]").description(
|
|
33329
|
+
"Read one fleet, or list every fleet when the id is omitted."
|
|
33330
|
+
).addHelpText(
|
|
33331
|
+
"after",
|
|
33332
|
+
`
|
|
33333
|
+
Notes:
|
|
33334
|
+
Status is the server's verdict. --check turns it into an exit code so a
|
|
33335
|
+
script can branch without parsing output: 0 converged, 6 anything else.
|
|
33336
|
+
--drift lists the members that have not settled and why.
|
|
33337
|
+
|
|
33338
|
+
Examples:
|
|
33339
|
+
deepline monitors fleets get --json
|
|
33340
|
+
deepline monitors fleets get account-job-openings --json
|
|
33341
|
+
deepline monitors fleets get account-job-openings --drift --limit 50 --json
|
|
33342
|
+
deepline monitors fleets get account-job-openings --check
|
|
33343
|
+
`
|
|
33344
|
+
).option("--drift", "Include the members that have not settled, and why").option("--limit <n>", "Maximum drift rows to return").option(
|
|
33345
|
+
"--check",
|
|
33346
|
+
"Exit 0 when converged and 6 otherwise, for scripts and agents"
|
|
33347
|
+
)
|
|
33348
|
+
).action(monitorsAction(handleMonitorFleetsGet));
|
|
33349
|
+
withJsonOption(
|
|
33350
|
+
fleets.command("deactivate <fleet-id>").description("Deactivate a fleet and the monitors it owns.").addHelpText(
|
|
33351
|
+
"after",
|
|
33352
|
+
`
|
|
33353
|
+
Notes:
|
|
33354
|
+
Destructive. --dry-run shows the blast radius without changing anything.
|
|
33355
|
+
An interactive terminal is shown that blast radius and asked to confirm;
|
|
33356
|
+
a non-interactive run must pass --yes. Re-running after a failure is safe.
|
|
33357
|
+
|
|
33358
|
+
Examples:
|
|
33359
|
+
deepline monitors fleets deactivate account-job-openings --dry-run
|
|
33360
|
+
deepline monitors fleets deactivate account-job-openings --yes --wait --json
|
|
33361
|
+
`
|
|
33362
|
+
).option("--dry-run", "Show the blast radius without deactivating").option("--wait", "Poll until the fleet reports deactivated").option(
|
|
33363
|
+
"--timeout <duration>",
|
|
33364
|
+
"How long --wait may poll: 500ms, 90s, 10m, 1h (default 10m)"
|
|
33365
|
+
).option(
|
|
33366
|
+
"--yes",
|
|
33367
|
+
"Skip the confirmation prompt (required non-interactively)"
|
|
33368
|
+
).option(
|
|
33369
|
+
"--idempotency-key <key>",
|
|
33370
|
+
"Stable retry key (generated and returned when omitted)"
|
|
33371
|
+
)
|
|
33372
|
+
).action(async (fleetId, options) => {
|
|
33373
|
+
let retryCommand = fleetDeactivateCommandLine(fleetId, options);
|
|
33374
|
+
try {
|
|
33375
|
+
const idempotencyKey = fleetIdempotencyKey(
|
|
33376
|
+
"deactivate",
|
|
33377
|
+
options.idempotencyKey
|
|
33378
|
+
);
|
|
33379
|
+
retryCommand = fleetDeactivateCommandLine(fleetId, {
|
|
33380
|
+
...options,
|
|
33381
|
+
idempotencyKey
|
|
33382
|
+
});
|
|
33383
|
+
await handleMonitorFleetsDeactivate(fleetId, options, idempotencyKey);
|
|
33384
|
+
} catch (error) {
|
|
33385
|
+
reportMonitorsFailure(error, { retryCommand });
|
|
33386
|
+
}
|
|
33387
|
+
});
|
|
32056
33388
|
const deployed = withJsonOption(
|
|
32057
33389
|
monitors.command("deployed", { hidden: true }).description("Alias of `monitors list` (plus get/update/delete aliases).").option(
|
|
32058
33390
|
"--status <status>",
|
|
@@ -32755,7 +34087,7 @@ async function readHiddenLine(prompt, streams = {}) {
|
|
|
32755
34087
|
}
|
|
32756
34088
|
let value = "";
|
|
32757
34089
|
inputStream.resume();
|
|
32758
|
-
return await new Promise((
|
|
34090
|
+
return await new Promise((resolve21, reject) => {
|
|
32759
34091
|
let settled = false;
|
|
32760
34092
|
const cleanup = () => {
|
|
32761
34093
|
inputStream.off("data", onData);
|
|
@@ -32773,7 +34105,7 @@ async function readHiddenLine(prompt, streams = {}) {
|
|
|
32773
34105
|
settled = true;
|
|
32774
34106
|
outputStream.write("\n");
|
|
32775
34107
|
cleanup();
|
|
32776
|
-
|
|
34108
|
+
resolve21(line);
|
|
32777
34109
|
};
|
|
32778
34110
|
const fail = (error) => {
|
|
32779
34111
|
if (settled) return;
|
|
@@ -32951,10 +34283,10 @@ import {
|
|
|
32951
34283
|
mkdirSync as mkdirSync11,
|
|
32952
34284
|
readFileSync as readFileSync14,
|
|
32953
34285
|
realpathSync as realpathSync4,
|
|
32954
|
-
writeFileSync as
|
|
34286
|
+
writeFileSync as writeFileSync15
|
|
32955
34287
|
} from "fs";
|
|
32956
34288
|
import { homedir as homedir9 } from "os";
|
|
32957
|
-
import { dirname as dirname16, join as join16, resolve as
|
|
34289
|
+
import { dirname as dirname16, join as join16, resolve as resolve16 } from "path";
|
|
32958
34290
|
|
|
32959
34291
|
// src/cli/installation-lifecycle.ts
|
|
32960
34292
|
import {
|
|
@@ -32964,7 +34296,7 @@ import {
|
|
|
32964
34296
|
realpathSync as realpathSync3,
|
|
32965
34297
|
rmSync as rmSync4
|
|
32966
34298
|
} from "fs";
|
|
32967
|
-
import { basename as basename6, dirname as dirname13, join as join13, relative as relative5, resolve as
|
|
34299
|
+
import { basename as basename6, dirname as dirname13, join as join13, relative as relative5, resolve as resolve15 } from "path";
|
|
32968
34300
|
var nodeFileSystem = {
|
|
32969
34301
|
exists: existsSync11,
|
|
32970
34302
|
isSymbolicLink(path) {
|
|
@@ -33079,14 +34411,14 @@ function isOwnedInstallerCommandPath(input2) {
|
|
|
33079
34411
|
if (!input2.commandPath || basename6(input2.commandPath) !== "deepline") {
|
|
33080
34412
|
return false;
|
|
33081
34413
|
}
|
|
33082
|
-
const commandPath =
|
|
33083
|
-
const fromHost = relative5(
|
|
34414
|
+
const commandPath = resolve15(input2.commandPath);
|
|
34415
|
+
const fromHost = relative5(resolve15(input2.hostDir), commandPath);
|
|
33084
34416
|
return fromHost !== "" && fromHost !== ".." && !fromHost.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`);
|
|
33085
34417
|
}
|
|
33086
34418
|
|
|
33087
34419
|
// src/cli/commands/skills.ts
|
|
33088
34420
|
import { spawn as spawn3 } from "child_process";
|
|
33089
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as
|
|
34421
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync14 } from "fs";
|
|
33090
34422
|
import { homedir as homedir8 } from "os";
|
|
33091
34423
|
import { dirname as dirname15, join as join15 } from "path";
|
|
33092
34424
|
|
|
@@ -33203,7 +34535,7 @@ import {
|
|
|
33203
34535
|
mkdirSync as mkdirSync9,
|
|
33204
34536
|
readFileSync as readFileSync12,
|
|
33205
34537
|
unlinkSync,
|
|
33206
|
-
writeFileSync as
|
|
34538
|
+
writeFileSync as writeFileSync13
|
|
33207
34539
|
} from "fs";
|
|
33208
34540
|
import { dirname as dirname14, join as join14 } from "path";
|
|
33209
34541
|
|
|
@@ -33261,7 +34593,7 @@ function readMarkedSkillsSyncVersion(path) {
|
|
|
33261
34593
|
function writeMarkedSkillsSyncVersion(path, version) {
|
|
33262
34594
|
try {
|
|
33263
34595
|
mkdirSync9(dirname14(path), { recursive: true });
|
|
33264
|
-
|
|
34596
|
+
writeFileSync13(path, `${version}
|
|
33265
34597
|
`, "utf-8");
|
|
33266
34598
|
} catch {
|
|
33267
34599
|
}
|
|
@@ -33414,7 +34746,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
|
|
|
33414
34746
|
return commands;
|
|
33415
34747
|
}
|
|
33416
34748
|
function runOneSkillsInstall(install) {
|
|
33417
|
-
return new Promise((
|
|
34749
|
+
return new Promise((resolve21) => {
|
|
33418
34750
|
const plan = resolveSkillsInstallSpawn(install);
|
|
33419
34751
|
const child = spawn2(plan.command, plan.args, {
|
|
33420
34752
|
stdio: ["ignore", "ignore", "pipe"],
|
|
@@ -33426,7 +34758,7 @@ function runOneSkillsInstall(install) {
|
|
|
33426
34758
|
stderr += chunk.toString("utf-8");
|
|
33427
34759
|
});
|
|
33428
34760
|
child.on("error", (error) => {
|
|
33429
|
-
|
|
34761
|
+
resolve21({
|
|
33430
34762
|
ok: false,
|
|
33431
34763
|
detail: `failed to start ${install.command}: ${error.message}`,
|
|
33432
34764
|
manualCommand: install.manualCommand
|
|
@@ -33434,11 +34766,11 @@ function runOneSkillsInstall(install) {
|
|
|
33434
34766
|
});
|
|
33435
34767
|
child.on("close", (code) => {
|
|
33436
34768
|
if (code === 0) {
|
|
33437
|
-
|
|
34769
|
+
resolve21({ ok: true, detail: "", manualCommand: install.manualCommand });
|
|
33438
34770
|
return;
|
|
33439
34771
|
}
|
|
33440
34772
|
const detail = stderr.trim();
|
|
33441
|
-
|
|
34773
|
+
resolve21({
|
|
33442
34774
|
ok: false,
|
|
33443
34775
|
detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
|
|
33444
34776
|
manualCommand: install.manualCommand
|
|
@@ -33720,7 +35052,7 @@ function readSkillsInstallState(path) {
|
|
|
33720
35052
|
}
|
|
33721
35053
|
}
|
|
33722
35054
|
function runProcess(command, args, cwd) {
|
|
33723
|
-
return new Promise((
|
|
35055
|
+
return new Promise((resolve21, reject) => {
|
|
33724
35056
|
const plan = resolveShellSpawn(command, args);
|
|
33725
35057
|
const child = spawn3(plan.command, plan.args, {
|
|
33726
35058
|
cwd,
|
|
@@ -33739,7 +35071,7 @@ function runProcess(command, args, cwd) {
|
|
|
33739
35071
|
process.stderr.write(`${SKILLS_NPX_PACKAGE} exited ${code}.
|
|
33740
35072
|
`);
|
|
33741
35073
|
}
|
|
33742
|
-
|
|
35074
|
+
resolve21(code ?? 1);
|
|
33743
35075
|
});
|
|
33744
35076
|
});
|
|
33745
35077
|
}
|
|
@@ -33867,7 +35199,7 @@ async function runSkillsCommand(options, dependencies = {}) {
|
|
|
33867
35199
|
);
|
|
33868
35200
|
}
|
|
33869
35201
|
mkdirSync10(dirname15(plan.statePath), { recursive: true });
|
|
33870
|
-
|
|
35202
|
+
writeFileSync14(
|
|
33871
35203
|
plan.statePath,
|
|
33872
35204
|
`${JSON.stringify(
|
|
33873
35205
|
{
|
|
@@ -33962,26 +35294,26 @@ function parseSetupPhases(value) {
|
|
|
33962
35294
|
if (!phase || typeof phase !== "object" || Array.isArray(phase)) {
|
|
33963
35295
|
return null;
|
|
33964
35296
|
}
|
|
33965
|
-
const
|
|
33966
|
-
if (!isSetupPhaseStatus(
|
|
33967
|
-
switch (
|
|
35297
|
+
const record2 = phase;
|
|
35298
|
+
if (!isSetupPhaseStatus(record2.status)) return null;
|
|
35299
|
+
switch (record2.status) {
|
|
33968
35300
|
case "pending":
|
|
33969
35301
|
case "in_progress":
|
|
33970
|
-
phases[name] = { status:
|
|
35302
|
+
phases[name] = { status: record2.status };
|
|
33971
35303
|
break;
|
|
33972
35304
|
case "complete":
|
|
33973
35305
|
phases[name] = {
|
|
33974
35306
|
status: "complete",
|
|
33975
|
-
...typeof
|
|
35307
|
+
...typeof record2.outcome === "string" ? { outcome: record2.outcome } : {}
|
|
33976
35308
|
};
|
|
33977
35309
|
break;
|
|
33978
35310
|
case "waiting":
|
|
33979
|
-
if (typeof
|
|
33980
|
-
phases[name] = { status: "waiting", outcome:
|
|
35311
|
+
if (typeof record2.outcome !== "string") return null;
|
|
35312
|
+
phases[name] = { status: "waiting", outcome: record2.outcome };
|
|
33981
35313
|
break;
|
|
33982
35314
|
case "failed":
|
|
33983
|
-
if (typeof
|
|
33984
|
-
phases[name] = { status: "failed", code:
|
|
35315
|
+
if (typeof record2.code !== "string") return null;
|
|
35316
|
+
phases[name] = { status: "failed", code: record2.code };
|
|
33985
35317
|
break;
|
|
33986
35318
|
}
|
|
33987
35319
|
}
|
|
@@ -34129,7 +35461,7 @@ function resolvePathCommands(command) {
|
|
|
34129
35461
|
);
|
|
34130
35462
|
return [
|
|
34131
35463
|
...new Set(
|
|
34132
|
-
String(lookup.stdout ?? "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((path) =>
|
|
35464
|
+
String(lookup.stdout ?? "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((path) => resolve16(path))
|
|
34133
35465
|
)
|
|
34134
35466
|
];
|
|
34135
35467
|
}
|
|
@@ -34177,11 +35509,11 @@ function pathsResolveToSameFile(left, right) {
|
|
|
34177
35509
|
try {
|
|
34178
35510
|
return realpathSync4(left) === realpathSync4(right);
|
|
34179
35511
|
} catch {
|
|
34180
|
-
return
|
|
35512
|
+
return resolve16(left) === resolve16(right);
|
|
34181
35513
|
}
|
|
34182
35514
|
}
|
|
34183
35515
|
function isKnownDeeplineCommand(path) {
|
|
34184
|
-
const entrypoint = process.argv[1] ?
|
|
35516
|
+
const entrypoint = process.argv[1] ? resolve16(process.argv[1]) : "";
|
|
34185
35517
|
let resolvedPath = path;
|
|
34186
35518
|
try {
|
|
34187
35519
|
resolvedPath = realpathSync4(path);
|
|
@@ -34207,7 +35539,7 @@ function inspectPathConflict() {
|
|
|
34207
35539
|
function writeSetupState(input2) {
|
|
34208
35540
|
const path = setupStatePath(input2.baseUrl, input2.scope, input2.root);
|
|
34209
35541
|
mkdirSync11(dirname16(path), { recursive: true });
|
|
34210
|
-
|
|
35542
|
+
writeFileSync15(
|
|
34211
35543
|
path,
|
|
34212
35544
|
`${JSON.stringify(
|
|
34213
35545
|
{
|
|
@@ -34334,7 +35666,7 @@ function buildDoctorAssessment(input2) {
|
|
|
34334
35666
|
const connected = input2.authStatus.payload?.connected === true;
|
|
34335
35667
|
const authScopeOk = input2.scope === "local" ? Boolean(projectAuth) : Boolean(apiKey && !projectAuth);
|
|
34336
35668
|
const skillsOk = skillsState?.scope === input2.scope && typeof skillsState.skillsVersion === "string" && Array.isArray(skillsState.agents) && skillsState.agents.length > 0;
|
|
34337
|
-
const runningCliPath = process.argv[1] ?
|
|
35669
|
+
const runningCliPath = process.argv[1] ? resolve16(process.argv[1]) : null;
|
|
34338
35670
|
const globalCli = input2.scope === "global" ? inspectGlobalCliAvailability() : null;
|
|
34339
35671
|
const pathGlobalCli = globalCli?.path ?? null;
|
|
34340
35672
|
const cliPath = input2.scope === "global" ? pathGlobalCli : runningCliPath;
|
|
@@ -34877,7 +36209,7 @@ import {
|
|
|
34877
36209
|
readFileSync as readFileSync15,
|
|
34878
36210
|
renameSync,
|
|
34879
36211
|
rmSync as rmSync5,
|
|
34880
|
-
writeFileSync as
|
|
36212
|
+
writeFileSync as writeFileSync16
|
|
34881
36213
|
} from "fs";
|
|
34882
36214
|
import { homedir as homedir10 } from "os";
|
|
34883
36215
|
import { dirname as dirname17, join as join17 } from "path";
|
|
@@ -34939,7 +36271,7 @@ function writeCliUpdatePreferences(preferences, homeDir2 = homedir10()) {
|
|
|
34939
36271
|
const tempPath = `${path}.${process.pid}.tmp`;
|
|
34940
36272
|
mkdirSync12(dirname17(path), { recursive: true });
|
|
34941
36273
|
try {
|
|
34942
|
-
|
|
36274
|
+
writeFileSync16(tempPath, `${JSON.stringify(preferences, null, 2)}
|
|
34943
36275
|
`, {
|
|
34944
36276
|
encoding: "utf8",
|
|
34945
36277
|
mode: 384
|
|
@@ -35004,7 +36336,7 @@ import {
|
|
|
35004
36336
|
renameSync as renameSync2,
|
|
35005
36337
|
rmSync as rmSync6,
|
|
35006
36338
|
unlinkSync as unlinkSync2,
|
|
35007
|
-
writeFileSync as
|
|
36339
|
+
writeFileSync as writeFileSync17
|
|
35008
36340
|
} from "fs";
|
|
35009
36341
|
import { homedir as homedir11 } from "os";
|
|
35010
36342
|
import {
|
|
@@ -35013,13 +36345,13 @@ import {
|
|
|
35013
36345
|
isAbsolute as isAbsolute7,
|
|
35014
36346
|
join as join19,
|
|
35015
36347
|
relative as relative7,
|
|
35016
|
-
resolve as
|
|
36348
|
+
resolve as resolve18
|
|
35017
36349
|
} from "path";
|
|
35018
36350
|
|
|
35019
36351
|
// src/cli/install-integrity.ts
|
|
35020
36352
|
import { createRequire } from "module";
|
|
35021
36353
|
import { existsSync as existsSync16, readFileSync as readFileSync16, statSync as statSync5 } from "fs";
|
|
35022
|
-
import { isAbsolute as isAbsolute6, join as join18, relative as relative6, resolve as
|
|
36354
|
+
import { isAbsolute as isAbsolute6, join as join18, relative as relative6, resolve as resolve17 } from "path";
|
|
35023
36355
|
var SDK_SIDECAR_CRITICAL_PACKAGE_FILES = [
|
|
35024
36356
|
"dist/cli/index.mjs",
|
|
35025
36357
|
"dist/index.mjs",
|
|
@@ -35044,8 +36376,8 @@ function safeRelativePath(value) {
|
|
|
35044
36376
|
}
|
|
35045
36377
|
function resolveContainedPath(root, value) {
|
|
35046
36378
|
if (!safeRelativePath(value)) return null;
|
|
35047
|
-
const target =
|
|
35048
|
-
const relativeTarget = relative6(
|
|
36379
|
+
const target = resolve17(root, value);
|
|
36380
|
+
const relativeTarget = relative6(resolve17(root), target);
|
|
35049
36381
|
if (!relativeTarget || relativeTarget.startsWith("..") || isAbsolute6(relativeTarget)) {
|
|
35050
36382
|
return null;
|
|
35051
36383
|
}
|
|
@@ -35271,8 +36603,8 @@ function resolvePythonSidecarUpdatePlan(options) {
|
|
|
35271
36603
|
const stateDir = sidecarStateDir(options);
|
|
35272
36604
|
if (!stateDir) return null;
|
|
35273
36605
|
const relativeEntrypoint = relative7(
|
|
35274
|
-
|
|
35275
|
-
|
|
36606
|
+
resolve18(stateDir),
|
|
36607
|
+
resolve18(options.entrypoint)
|
|
35276
36608
|
);
|
|
35277
36609
|
if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || isAbsolute7(relativeEntrypoint)) {
|
|
35278
36610
|
return null;
|
|
@@ -35306,7 +36638,7 @@ function resolvePythonSidecarUpdatePlan(options) {
|
|
|
35306
36638
|
};
|
|
35307
36639
|
}
|
|
35308
36640
|
function findRepoBackedSdkRoot(startPath) {
|
|
35309
|
-
let current =
|
|
36641
|
+
let current = resolve18(startPath);
|
|
35310
36642
|
while (true) {
|
|
35311
36643
|
if (existsSync17(join19(current, "package.json")) && existsSync17(join19(current, "bin", "deepline-dev.ts"))) {
|
|
35312
36644
|
const parent2 = dirname18(current);
|
|
@@ -35325,7 +36657,7 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint, env) {
|
|
|
35325
36657
|
try {
|
|
35326
36658
|
return realpathSync5(entrypoint);
|
|
35327
36659
|
} catch {
|
|
35328
|
-
return
|
|
36660
|
+
return resolve18(entrypoint);
|
|
35329
36661
|
}
|
|
35330
36662
|
})();
|
|
35331
36663
|
const parts = normalized.split(/[\\/]+/);
|
|
@@ -35341,9 +36673,9 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint, env) {
|
|
|
35341
36673
|
const knownWindowsPrefixes = [
|
|
35342
36674
|
env.npm_config_prefix,
|
|
35343
36675
|
env.APPDATA ? join19(env.APPDATA, "npm") : void 0
|
|
35344
|
-
].filter((value) => Boolean(value)).map((value) =>
|
|
36676
|
+
].filter((value) => Boolean(value)).map((value) => resolve18(value).replace(/\\/g, "/").toLowerCase());
|
|
35345
36677
|
if (!knownWindowsPrefixes.includes(
|
|
35346
|
-
|
|
36678
|
+
resolve18(directPrefix).replace(/\\/g, "/").toLowerCase()
|
|
35347
36679
|
)) {
|
|
35348
36680
|
return null;
|
|
35349
36681
|
}
|
|
@@ -35356,9 +36688,9 @@ function normalizedNpmPrefix(value) {
|
|
|
35356
36688
|
if (!trimmed) return null;
|
|
35357
36689
|
const normalized = (() => {
|
|
35358
36690
|
try {
|
|
35359
|
-
return realpathSync5(
|
|
36691
|
+
return realpathSync5(resolve18(trimmed));
|
|
35360
36692
|
} catch {
|
|
35361
|
-
return
|
|
36693
|
+
return resolve18(trimmed);
|
|
35362
36694
|
}
|
|
35363
36695
|
})().replace(/\\/g, "/");
|
|
35364
36696
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
@@ -35383,7 +36715,7 @@ function isHomebrewFormulaEntrypoint(entrypoint) {
|
|
|
35383
36715
|
try {
|
|
35384
36716
|
return realpathSync5(entrypoint);
|
|
35385
36717
|
} catch {
|
|
35386
|
-
return
|
|
36718
|
+
return resolve18(entrypoint);
|
|
35387
36719
|
}
|
|
35388
36720
|
})();
|
|
35389
36721
|
const parts = normalized.split(/[\\/]+/);
|
|
@@ -35393,7 +36725,7 @@ function isHomebrewFormulaEntrypoint(entrypoint) {
|
|
|
35393
36725
|
function resolveUpdatePlan(options = {}) {
|
|
35394
36726
|
const env = options.env ?? process.env;
|
|
35395
36727
|
const homeDir2 = options.homeDir ?? homedir11();
|
|
35396
|
-
const entrypoint = options.entrypoint ?? (process.argv[1] ?
|
|
36728
|
+
const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve18(process.argv[1]) : "");
|
|
35397
36729
|
const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname18(entrypoint)) : null;
|
|
35398
36730
|
if (sourceRoot) {
|
|
35399
36731
|
return {
|
|
@@ -35487,7 +36819,7 @@ function writeAutoUpdateFailure(plan, exitCode) {
|
|
|
35487
36819
|
};
|
|
35488
36820
|
try {
|
|
35489
36821
|
mkdirSync13(dirname18(path), { recursive: true });
|
|
35490
|
-
|
|
36822
|
+
writeFileSync17(path, `${JSON.stringify(marker, null, 2)}
|
|
35491
36823
|
`, "utf8");
|
|
35492
36824
|
} catch {
|
|
35493
36825
|
}
|
|
@@ -35679,7 +37011,7 @@ function writeSidecarLauncher(input2) {
|
|
|
35679
37011
|
)
|
|
35680
37012
|
];
|
|
35681
37013
|
if (process.platform === "win32") {
|
|
35682
|
-
|
|
37014
|
+
writeFileSync17(
|
|
35683
37015
|
input2.path,
|
|
35684
37016
|
[
|
|
35685
37017
|
`@set DEEPLINE_HOST_URL=${input2.hostUrl.replace(/\r?\n/g, "")}`,
|
|
@@ -35702,7 +37034,7 @@ function writeSidecarLauncher(input2) {
|
|
|
35702
37034
|
);
|
|
35703
37035
|
return;
|
|
35704
37036
|
}
|
|
35705
|
-
|
|
37037
|
+
writeFileSync17(
|
|
35706
37038
|
input2.path,
|
|
35707
37039
|
[
|
|
35708
37040
|
"#!/usr/bin/env sh",
|
|
@@ -35736,7 +37068,7 @@ async function runPythonSidecarUpdatePlan(plan) {
|
|
|
35736
37068
|
);
|
|
35737
37069
|
rmSync6(tempDir, { recursive: true, force: true });
|
|
35738
37070
|
mkdirSync13(tempDir, { recursive: true });
|
|
35739
|
-
|
|
37071
|
+
writeFileSync17(join19(tempDir, "package.json"), NPM_SDK_SIDECAR_PACKAGE_JSON);
|
|
35740
37072
|
const env = {
|
|
35741
37073
|
...process.env,
|
|
35742
37074
|
PATH: `${dirname18(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
|
|
@@ -35859,27 +37191,27 @@ async function runPythonSidecarUpdatePlan(plan) {
|
|
|
35859
37191
|
nodeBin: plan.nodeBin,
|
|
35860
37192
|
entryPath: finalEntryPath
|
|
35861
37193
|
});
|
|
35862
|
-
|
|
37194
|
+
writeFileSync17(
|
|
35863
37195
|
join19(plan.stateDir, ".version"),
|
|
35864
37196
|
`${installedVersion}
|
|
35865
37197
|
`,
|
|
35866
37198
|
"utf8"
|
|
35867
37199
|
);
|
|
35868
|
-
|
|
37200
|
+
writeFileSync17(
|
|
35869
37201
|
join19(plan.stateDir, ".install-method"),
|
|
35870
37202
|
"python-sidecar\n",
|
|
35871
37203
|
"utf8"
|
|
35872
37204
|
);
|
|
35873
|
-
|
|
37205
|
+
writeFileSync17(
|
|
35874
37206
|
join19(plan.stateDir, ".command-path"),
|
|
35875
37207
|
`${plan.sidecarPath}
|
|
35876
37208
|
`,
|
|
35877
37209
|
"utf8"
|
|
35878
37210
|
);
|
|
35879
|
-
|
|
35880
|
-
|
|
37211
|
+
writeFileSync17(join19(plan.stateDir, ".runner"), "node\n", "utf8");
|
|
37212
|
+
writeFileSync17(join19(plan.stateDir, ".node-bin"), `${plan.nodeBin}
|
|
35881
37213
|
`, "utf8");
|
|
35882
|
-
|
|
37214
|
+
writeFileSync17(
|
|
35883
37215
|
join19(plan.stateDir, ".entry-path"),
|
|
35884
37216
|
`${finalEntryPath}
|
|
35885
37217
|
`,
|
|
@@ -36812,17 +38144,17 @@ import {
|
|
|
36812
38144
|
existsSync as existsSync18,
|
|
36813
38145
|
mkdtempSync,
|
|
36814
38146
|
readFileSync as readFileSync18,
|
|
36815
|
-
writeFileSync as
|
|
38147
|
+
writeFileSync as writeFileSync19
|
|
36816
38148
|
} from "fs";
|
|
36817
38149
|
import { tmpdir as tmpdir5 } from "os";
|
|
36818
|
-
import { join as join21, resolve as
|
|
38150
|
+
import { join as join21, resolve as resolve19 } from "path";
|
|
36819
38151
|
|
|
36820
38152
|
// src/tool-output.ts
|
|
36821
38153
|
import {
|
|
36822
38154
|
closeSync as closeSync3,
|
|
36823
38155
|
mkdirSync as mkdirSync14,
|
|
36824
38156
|
openSync as openSync3,
|
|
36825
|
-
writeFileSync as
|
|
38157
|
+
writeFileSync as writeFileSync18,
|
|
36826
38158
|
writeSync
|
|
36827
38159
|
} from "fs";
|
|
36828
38160
|
import { homedir as homedir12 } from "os";
|
|
@@ -36960,7 +38292,7 @@ function ensureOutputDir() {
|
|
|
36960
38292
|
function writeJsonOutputFile(payload, stem) {
|
|
36961
38293
|
const outputDir = ensureOutputDir();
|
|
36962
38294
|
const outputPath = join20(outputDir, `${stem}_${Date.now()}.json`);
|
|
36963
|
-
|
|
38295
|
+
writeFileSync18(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
36964
38296
|
return outputPath;
|
|
36965
38297
|
}
|
|
36966
38298
|
function writeCsvOutputFile(rows, stem, options) {
|
|
@@ -37301,9 +38633,9 @@ function requiredInputIds(tool) {
|
|
|
37301
38633
|
return toolInputFieldsForDisplay(inputSchema).filter((field) => field.required === true).map((field) => String(field.name ?? "")).filter(Boolean);
|
|
37302
38634
|
}
|
|
37303
38635
|
function notConnectedSuffix(tool) {
|
|
37304
|
-
const
|
|
37305
|
-
const status = stringField2(
|
|
37306
|
-
const connected =
|
|
38636
|
+
const record2 = tool;
|
|
38637
|
+
const status = stringField2(record2, "credentialStatus", "credential_status");
|
|
38638
|
+
const connected = record2.connected;
|
|
37307
38639
|
if (status === "requires_connection" || connected === false) {
|
|
37308
38640
|
return " - \u26A0 requires your credentials \u2014 not connected (connect to use)";
|
|
37309
38641
|
}
|
|
@@ -37678,19 +39010,19 @@ function printPlayAliasToolError(toolId, play) {
|
|
|
37678
39010
|
console.error(playAliasToolErrorMessage(toolId, play));
|
|
37679
39011
|
}
|
|
37680
39012
|
function isPlayLikeTool(tool) {
|
|
37681
|
-
const
|
|
37682
|
-
if (
|
|
37683
|
-
const playExpansion = recordField2(
|
|
39013
|
+
const record2 = tool;
|
|
39014
|
+
if (record2.isPlay === true || record2.is_play === true) return true;
|
|
39015
|
+
const playExpansion = recordField2(record2, "playExpansion", "play_expansion");
|
|
37684
39016
|
if (Object.keys(playExpansion).length > 0) return true;
|
|
37685
|
-
const toolId = typeof
|
|
39017
|
+
const toolId = typeof record2.toolId === "string" ? record2.toolId : "";
|
|
37686
39018
|
return toolId.endsWith("_waterfall");
|
|
37687
39019
|
}
|
|
37688
39020
|
function isMonitorTypeTool(tool) {
|
|
37689
39021
|
return stringField2(tool, "kind") === "monitor_type";
|
|
37690
39022
|
}
|
|
37691
39023
|
function playReferenceForTool(tool) {
|
|
37692
|
-
const
|
|
37693
|
-
const declared = stringField2(
|
|
39024
|
+
const record2 = tool;
|
|
39025
|
+
const declared = stringField2(record2, "playReference", "play_reference");
|
|
37694
39026
|
if (declared.startsWith("prebuilt/")) {
|
|
37695
39027
|
return declared;
|
|
37696
39028
|
}
|
|
@@ -38648,12 +39980,12 @@ function singleLineText(value, maxLength = 260) {
|
|
|
38648
39980
|
return `${text.slice(0, maxLength - 3).trimEnd()}...`;
|
|
38649
39981
|
}
|
|
38650
39982
|
function listedToolDescription(tool) {
|
|
38651
|
-
const
|
|
38652
|
-
return singleLineText(
|
|
39983
|
+
const record2 = tool;
|
|
39984
|
+
return singleLineText(record2.bestFor ?? record2.best_for ?? tool.description);
|
|
38653
39985
|
}
|
|
38654
39986
|
function formatListedToolCost(tool) {
|
|
38655
|
-
const
|
|
38656
|
-
const pricing = recordField2(
|
|
39987
|
+
const record2 = tool;
|
|
39988
|
+
const pricing = recordField2(record2, "pricing");
|
|
38657
39989
|
const displayText = stringField2(pricing, "displayText", "display_text");
|
|
38658
39990
|
return displayText ? `Cost: ${displayText}` : "";
|
|
38659
39991
|
}
|
|
@@ -38934,10 +40266,10 @@ function normalizeOutputFormat(raw) {
|
|
|
38934
40266
|
}
|
|
38935
40267
|
function resolveAtFilePath(rawPath) {
|
|
38936
40268
|
const trimmed = rawPath.trim();
|
|
38937
|
-
const resolved =
|
|
40269
|
+
const resolved = resolve19(trimmed);
|
|
38938
40270
|
if (existsSync18(resolved)) return resolved;
|
|
38939
40271
|
if (process.platform !== "win32" && trimmed.includes("\\")) {
|
|
38940
|
-
const normalized =
|
|
40272
|
+
const normalized = resolve19(trimmed.replace(/\\/g, "/"));
|
|
38941
40273
|
if (existsSync18(normalized)) return normalized;
|
|
38942
40274
|
}
|
|
38943
40275
|
return resolved;
|
|
@@ -39026,7 +40358,7 @@ function parseExecuteOptions(args) {
|
|
|
39026
40358
|
continue;
|
|
39027
40359
|
}
|
|
39028
40360
|
if ((arg === "--out" || arg === "-o") && args[index + 1]) {
|
|
39029
|
-
outPath =
|
|
40361
|
+
outPath = resolve19(args[++index]);
|
|
39030
40362
|
continue;
|
|
39031
40363
|
}
|
|
39032
40364
|
throw new Error(`Unknown option: ${arg}`);
|
|
@@ -39101,7 +40433,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
|
39101
40433
|
description: ${JSON.stringify(`Seed ${input2.toolId} rows into a Deepline workflow-ready dataset.`)},
|
|
39102
40434
|
});
|
|
39103
40435
|
`;
|
|
39104
|
-
|
|
40436
|
+
writeFileSync19(scriptPath, script, { encoding: "utf-8", mode: 384 });
|
|
39105
40437
|
return {
|
|
39106
40438
|
path: scriptPath,
|
|
39107
40439
|
sourceCode: script,
|
|
@@ -39527,7 +40859,7 @@ Examples:
|
|
|
39527
40859
|
|
|
39528
40860
|
// src/cli/commands/workflow.ts
|
|
39529
40861
|
import { mkdir as mkdir5, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
39530
|
-
import { dirname as dirname20, join as join22, resolve as
|
|
40862
|
+
import { dirname as dirname20, join as join22, resolve as resolve20 } from "path";
|
|
39531
40863
|
|
|
39532
40864
|
// src/cli/workflow-to-play.ts
|
|
39533
40865
|
import { createHash as createHash5 } from "crypto";
|
|
@@ -39733,9 +41065,9 @@ function clientWithTimeout(timeoutSeconds) {
|
|
|
39733
41065
|
}
|
|
39734
41066
|
function readStatus(payload) {
|
|
39735
41067
|
if (!payload || typeof payload !== "object") return null;
|
|
39736
|
-
const
|
|
39737
|
-
if (typeof
|
|
39738
|
-
const run =
|
|
41068
|
+
const record2 = payload;
|
|
41069
|
+
if (typeof record2.status === "string") return record2.status;
|
|
41070
|
+
const run = record2.run;
|
|
39739
41071
|
if (run && typeof run === "object") {
|
|
39740
41072
|
const status = run.status;
|
|
39741
41073
|
if (typeof status === "string") return status;
|
|
@@ -39744,7 +41076,7 @@ function readStatus(payload) {
|
|
|
39744
41076
|
}
|
|
39745
41077
|
async function readJsonOption(payload, file) {
|
|
39746
41078
|
if (file) {
|
|
39747
|
-
const raw = await readFile4(
|
|
41079
|
+
const raw = await readFile4(resolve20(file), "utf8");
|
|
39748
41080
|
return JSON.parse(raw);
|
|
39749
41081
|
}
|
|
39750
41082
|
if (payload) {
|
|
@@ -39778,7 +41110,7 @@ async function transformOne(api, workflowId, outDir, publish) {
|
|
|
39778
41110
|
revision.config,
|
|
39779
41111
|
{ workflowName: workflow.name, version: revision.version }
|
|
39780
41112
|
);
|
|
39781
|
-
const file = join22(
|
|
41113
|
+
const file = join22(resolve20(outDir), `${compiled.playName}.play.ts`);
|
|
39782
41114
|
await mkdir5(dirname20(file), { recursive: true });
|
|
39783
41115
|
await writeFile5(file, compiled.sourceCode, "utf8");
|
|
39784
41116
|
let published = false;
|
|
@@ -40158,7 +41490,7 @@ function isDowngradeAutoUpdateResponse(response) {
|
|
|
40158
41490
|
return compareSemver(target, current) < 0;
|
|
40159
41491
|
}
|
|
40160
41492
|
function relaunchCurrentCommand(plan) {
|
|
40161
|
-
return new Promise((
|
|
41493
|
+
return new Promise((resolve21) => {
|
|
40162
41494
|
const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
|
|
40163
41495
|
const args = plan.kind === "python-sidecar" ? process.argv.slice(2) : process.argv.slice(1);
|
|
40164
41496
|
const child = spawn5(command, args, {
|
|
@@ -40174,9 +41506,9 @@ function relaunchCurrentCommand(plan) {
|
|
|
40174
41506
|
`Deepline SDK/CLI updated, but relaunch failed: ${error.message}
|
|
40175
41507
|
`
|
|
40176
41508
|
);
|
|
40177
|
-
|
|
41509
|
+
resolve21(1);
|
|
40178
41510
|
});
|
|
40179
|
-
child.on("close", (code) =>
|
|
41511
|
+
child.on("close", (code) => resolve21(code ?? 1));
|
|
40180
41512
|
});
|
|
40181
41513
|
}
|
|
40182
41514
|
async function maybeAutoUpdateAndRelaunch(response, baseUrl) {
|
|
@@ -40324,8 +41656,8 @@ function classifyNetworkFailure(error) {
|
|
|
40324
41656
|
let current = error;
|
|
40325
41657
|
while (current && !seen.has(current)) {
|
|
40326
41658
|
seen.add(current);
|
|
40327
|
-
const
|
|
40328
|
-
const code = String(
|
|
41659
|
+
const record2 = typeof current === "object" && current !== null ? current : {};
|
|
41660
|
+
const code = String(record2.code ?? "").toLowerCase();
|
|
40329
41661
|
const name = current instanceof Error ? current.name.toLowerCase() : "";
|
|
40330
41662
|
const text = String(
|
|
40331
41663
|
current instanceof Error ? current.message : current
|
|
@@ -40352,7 +41684,7 @@ function classifyNetworkFailure(error) {
|
|
|
40352
41684
|
if (combined.includes("ssl") || combined.includes("tls") || combined.includes("unexpected_eof_while_reading")) {
|
|
40353
41685
|
return "network_ssl_error";
|
|
40354
41686
|
}
|
|
40355
|
-
current =
|
|
41687
|
+
current = record2.cause ?? record2.context;
|
|
40356
41688
|
}
|
|
40357
41689
|
return "network_error";
|
|
40358
41690
|
}
|