@indigoai-us/hq-cloud 6.18.16 → 6.18.17
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/bin/sync-runner-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +9 -1
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner-company.test.js +184 -3
- package/dist/bin/sync-runner-company.test.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +8 -0
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +57 -2
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/rescue-core.d.ts.map +1 -1
- package/dist/cli/rescue-core.js +21 -6
- package/dist/cli/rescue-core.js.map +1 -1
- package/dist/cli/rescue-rsync-status.test.js +23 -0
- package/dist/cli/rescue-rsync-status.test.js.map +1 -1
- package/dist/cli/share-plan-limit-presign.test.d.ts +2 -0
- package/dist/cli/share-plan-limit-presign.test.d.ts.map +1 -0
- package/dist/cli/share-plan-limit-presign.test.js +271 -0
- package/dist/cli/share-plan-limit-presign.test.js.map +1 -0
- package/dist/cli/share.d.ts +22 -0
- package/dist/cli/share.d.ts.map +1 -1
- package/dist/cli/share.js +151 -25
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/share.test.js +262 -18
- package/dist/cli/share.test.js.map +1 -1
- package/dist/cli/sync.d.ts +38 -1
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +2 -1
- package/dist/cli/sync.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/object-io.d.ts +40 -0
- package/dist/object-io.d.ts.map +1 -1
- package/dist/object-io.js +122 -5
- package/dist/object-io.js.map +1 -1
- package/dist/object-io.test.js +144 -1
- package/dist/object-io.test.js.map +1 -1
- package/dist/plan-limit-pause.d.ts +61 -0
- package/dist/plan-limit-pause.d.ts.map +1 -0
- package/dist/plan-limit-pause.js +252 -0
- package/dist/plan-limit-pause.js.map +1 -0
- package/dist/plan-limit-pause.test.d.ts +2 -0
- package/dist/plan-limit-pause.test.d.ts.map +1 -0
- package/dist/plan-limit-pause.test.js +150 -0
- package/dist/plan-limit-pause.test.js.map +1 -0
- package/dist/plan-limit.d.ts +87 -0
- package/dist/plan-limit.d.ts.map +1 -0
- package/dist/plan-limit.fixtures.d.ts +34 -0
- package/dist/plan-limit.fixtures.d.ts.map +1 -0
- package/dist/plan-limit.fixtures.js +96 -0
- package/dist/plan-limit.fixtures.js.map +1 -0
- package/dist/plan-limit.js +157 -0
- package/dist/plan-limit.js.map +1 -0
- package/dist/plan-limit.test.d.ts +2 -0
- package/dist/plan-limit.test.d.ts.map +1 -0
- package/dist/plan-limit.test.js +132 -0
- package/dist/plan-limit.test.js.map +1 -0
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/mutation-client.d.ts +14 -2
- package/dist/sync/mutation-client.d.ts.map +1 -1
- package/dist/sync/mutation-client.js +34 -2
- package/dist/sync/mutation-client.js.map +1 -1
- package/dist/sync/mutation-client.test.js +49 -0
- package/dist/sync/mutation-client.test.js.map +1 -1
- package/dist/vault-client.d.ts +49 -6
- package/dist/vault-client.d.ts.map +1 -1
- package/dist/vault-client.js +115 -43
- package/dist/vault-client.js.map +1 -1
- package/dist/vault-client.test.js +86 -10
- package/dist/vault-client.test.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/share.js
CHANGED
|
@@ -13,7 +13,7 @@ import { createSyncProgressRecorder } from "../sync-progress.js";
|
|
|
13
13
|
import { localPathForVaultKey, vaultKeyForLocalPath } from "../local-path-codec.js";
|
|
14
14
|
import { uploadFile, uploadSymlink, toPosixKey, headRemoteFile, readVerifiedRemoteSymlinkTarget, deleteRemoteFile, downloadFile, primeObjectTransport, primeUploads, publishedContentHash, setUploadContentHash, WindowsSymlinkPrivilegeError, WINDOWS_SYMLINK_PRIVILEGE_REMEDY, WindowsRenameBlockedError, WINDOWS_RENAME_BLOCKED_REMEDY, renameOrRaiseWindowsBlocked, } from "../s3.js";
|
|
15
15
|
import * as crypto from "crypto";
|
|
16
|
-
import { bindObjectIOToContext, PresignObjectIO, RateLimitedError, S3SdkObjectIO, } from "../object-io.js";
|
|
16
|
+
import { bindObjectIOToContext, PresignObjectIO, RateLimitedError, resolveObjectIO, S3SdkObjectIO, } from "../object-io.js";
|
|
17
17
|
import { primePrivateFolderUpload } from "../private-folder-transport.js";
|
|
18
18
|
import { isUnderAnyRoot, readJournalForPass, readJournalScoped, writeJournal, hashFile, hashSymlinkTarget, journalRows, journalEntryMatchesStat, journalFingerprintMatchesStat, dropJournalDecodeWindow, timestampsTooCoarseToTrust, updateEntry, PrematureJournalEntryError, removeEntry, isTombstone, normalizeEtag, PERSONAL_VAULT_JOURNAL_SLUG, migratePersonalVaultJournal, migrateToV2, } from "../journal.js";
|
|
19
19
|
import { createIgnoreFilter, hasControlCharacters, isExpectedIgnore, isSecretPatternIgnore, isWithinSizeLimit, } from "../ignore.js";
|
|
@@ -32,7 +32,9 @@ import { isOntologyEntityKey, ONTOLOGY_MULTI_WRITER_FLAG, resolveOntologyEntityP
|
|
|
32
32
|
import { entityIsFreshForCreate, outboxAllowsEntityPush, readOntologyOutbox, } from "../lib/ontology-outbox.js";
|
|
33
33
|
import { resolveSkillRegisterLandedBytes } from "../lib/skill-register-landed-bytes.js";
|
|
34
34
|
import { resolvePersonalConnectorSettingsSync } from "../lib/personal-connector-settings-sync.js";
|
|
35
|
-
import { VaultAuthError, VaultClient, VaultClientError, VaultConflictError, VaultPermissionDeniedError, } from "../vault-client.js";
|
|
35
|
+
import { planLimitRefusalFromError, VaultAuthError, VaultClient, VaultClientError, VaultConflictError, VaultPermissionDeniedError, } from "../vault-client.js";
|
|
36
|
+
import { formatPlanLimitNotice } from "../plan-limit.js";
|
|
37
|
+
import { PlanLimitPauseStore, planLimitPauseNow, PLAN_LIMIT_PAUSE_RETRY_MS, } from "../plan-limit-pause.js";
|
|
36
38
|
import { describeError } from "../lib/describe-error.js";
|
|
37
39
|
import { isTransientHttpStatusError } from "../lib/net-errors.js";
|
|
38
40
|
import { isRetryableIdentityRefusal, isTerminalIdentityRefusal, } from "../cognito-auth.js";
|
|
@@ -1243,6 +1245,8 @@ function createShareCounters() {
|
|
|
1243
1245
|
filesRefusedStale: 0,
|
|
1244
1246
|
filesSuppressedByTombstone: 0,
|
|
1245
1247
|
uploadedPaths: [],
|
|
1248
|
+
filesPlanLimited: 0,
|
|
1249
|
+
planLimitedPaths: [],
|
|
1246
1250
|
};
|
|
1247
1251
|
}
|
|
1248
1252
|
const CANONICAL_COMPANY_SKILL_RE = /^skills\/([a-z0-9][a-z0-9-]*)\/SKILL\.md$/;
|
|
@@ -2051,15 +2055,48 @@ async function refreshPushJournalAfterWalk(run, collectedKeys = [], deleteScopeR
|
|
|
2051
2055
|
await yieldToCooperativeCheckpoint(checkpointWork, run.options.cooperativeCheckpoint, true);
|
|
2052
2056
|
}
|
|
2053
2057
|
}
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2058
|
+
/** Refused paths carried on a `plan-limit` event and in `ShareResult`. */
|
|
2059
|
+
const PLAN_LIMITED_PATHS_CAP = 50;
|
|
2060
|
+
/**
|
|
2061
|
+
* One files admission check for a vault with paused uploads (see
|
|
2062
|
+
* `ObjectIO.checkFilesAdmission`). `allowed` clears the vault's pauses so the
|
|
2063
|
+
* files upload in this pass; `refused` keeps them and refreshes the stored
|
|
2064
|
+
* refusal; anything else keeps the hourly retry. Never throws: an unknown
|
|
2065
|
+
* answer is logged at debug level only.
|
|
2066
|
+
*/
|
|
2067
|
+
async function checkPlanLimitAdmission(run, pauses) {
|
|
2068
|
+
if (!run.ctx.uid.startsWith("cmp_"))
|
|
2069
|
+
return;
|
|
2070
|
+
let outcome;
|
|
2071
|
+
try {
|
|
2072
|
+
const io = resolveObjectIO(run.ctx);
|
|
2073
|
+
if (typeof io.checkFilesAdmission !== "function")
|
|
2074
|
+
return;
|
|
2075
|
+
outcome = await io.checkFilesAdmission();
|
|
2076
|
+
}
|
|
2077
|
+
catch (err) {
|
|
2078
|
+
outcome = { state: "unknown", reason: describeError(err) };
|
|
2059
2079
|
}
|
|
2060
|
-
if (
|
|
2061
|
-
|
|
2062
|
-
|
|
2080
|
+
if (outcome.state === "allowed") {
|
|
2081
|
+
pauses.clear();
|
|
2082
|
+
}
|
|
2083
|
+
else if (outcome.state === "refused") {
|
|
2084
|
+
pauses.refreshRefusal(outcome.refusal);
|
|
2085
|
+
}
|
|
2086
|
+
else {
|
|
2087
|
+
debugPlanLimit({
|
|
2088
|
+
event: "plan-limit.admission.unknown",
|
|
2089
|
+
companyUid: run.ctx.uid,
|
|
2090
|
+
reason: outcome.reason,
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
/** Debug-level diagnostic on stderr, only when `LOG_LEVEL` is debug/trace. */
|
|
2095
|
+
function debugPlanLimit(fields) {
|
|
2096
|
+
const level = process.env.LOG_LEVEL;
|
|
2097
|
+
if (level !== "debug" && level !== "trace")
|
|
2098
|
+
return;
|
|
2099
|
+
process.stderr.write(`${JSON.stringify({ level: "debug", component: "plan-limit", ...fields })}\n`);
|
|
2063
2100
|
}
|
|
2064
2101
|
async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
2065
2102
|
counters.filesSkipped += pushPlan.preplannedFilesSkipped;
|
|
@@ -2085,21 +2122,51 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2085
2122
|
const entry = journalRows(run.journal).get(item.relativePath);
|
|
2086
2123
|
return entry !== undefined && entry.hash === item.localHash;
|
|
2087
2124
|
};
|
|
2125
|
+
// Plan-limit pauses (plan-limit-pause.ts). Read once per pass; the pass's
|
|
2126
|
+
// refusals and successes are applied in finishPlanLimitPass below.
|
|
2127
|
+
const planLimitPauses = PlanLimitPauseStore.open(run.ctx.uid);
|
|
2128
|
+
const planLimitPassStartedAt = planLimitPauseNow();
|
|
2129
|
+
const honorPlanLimitPauses = run.options.planLimitPause === true;
|
|
2130
|
+
const uploadedBeforePass = counters.filesUploaded;
|
|
2131
|
+
// Refused by the server in this pass.
|
|
2132
|
+
const planLimitRefusedPaths = new Set();
|
|
2133
|
+
// Skipped without a presign because an earlier refusal paused them, with
|
|
2134
|
+
// the end of each pause window.
|
|
2135
|
+
const planLimitPausedSkips = new Map();
|
|
2136
|
+
let planLimitRefusal;
|
|
2137
|
+
const notePlanLimitedPath = (relativePath) => {
|
|
2138
|
+
counters.filesPlanLimited++;
|
|
2139
|
+
if (counters.planLimitedPaths.length < PLAN_LIMITED_PATHS_CAP) {
|
|
2140
|
+
counters.planLimitedPaths.push(relativePath);
|
|
2141
|
+
}
|
|
2142
|
+
};
|
|
2143
|
+
const planLimitPausedUntil = (item) => honorPlanLimitPauses
|
|
2144
|
+
? planLimitPauses.pausedUntil(item.relativePath, planLimitPassStartedAt)
|
|
2145
|
+
: undefined;
|
|
2146
|
+
const isPlanLimitPaused = (item) => planLimitPausedUntil(item) !== undefined;
|
|
2088
2147
|
// Prime from the preview's likely uploads for transport efficiency. The
|
|
2089
2148
|
// candidate is refreshed after the plan event and tombstone suppression is
|
|
2090
2149
|
// applied BEFORE any presigns are minted. The queue below still re-plans
|
|
2091
2150
|
// every preview item before admission, so a later edit cannot disappear from
|
|
2092
2151
|
// the pass or carry a stale hash into its journal entry.
|
|
2093
|
-
const
|
|
2152
|
+
const plannedUploadCandidates = [];
|
|
2094
2153
|
for (const previewItem of pushPlan.items) {
|
|
2095
2154
|
if (previewItem.action !== "upload")
|
|
2096
2155
|
continue;
|
|
2097
2156
|
const item = replanPushItemAtExecution(previewItem, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.ontologyEntityPush);
|
|
2098
|
-
if (item?.action === "upload" &&
|
|
2099
|
-
|
|
2100
|
-
initiallyPlannedUploads.push(item);
|
|
2157
|
+
if (item?.action === "upload" && !isUploadSuppressedByTombstone(item)) {
|
|
2158
|
+
plannedUploadCandidates.push(item);
|
|
2101
2159
|
}
|
|
2102
2160
|
}
|
|
2161
|
+
// Before skipping paused files, ask the company vault once whether it
|
|
2162
|
+
// accepts uploads again (an upgrade, or files deleted to get under the
|
|
2163
|
+
// limit). Allowed: drop the pauses and upload them in this pass. Refused:
|
|
2164
|
+
// keep them. Anything else: keep the hourly retry.
|
|
2165
|
+
if (plannedUploadCandidates.some(isPlanLimitPaused)) {
|
|
2166
|
+
await checkPlanLimitAdmission(run, planLimitPauses);
|
|
2167
|
+
}
|
|
2168
|
+
// A paused file is not uploaded this pass, so do not presign it either.
|
|
2169
|
+
const initiallyPlannedUploads = plannedUploadCandidates.filter((item) => !isPlanLimitPaused(item));
|
|
2103
2170
|
if (run.options.cooperativeCheckpoint?.shouldAbort?.() === true) {
|
|
2104
2171
|
return {
|
|
2105
2172
|
aborted: true,
|
|
@@ -2122,18 +2189,59 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2122
2189
|
let aborted = false;
|
|
2123
2190
|
let abortFlightConflictPaths = [];
|
|
2124
2191
|
let hadUploadFailure = false;
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2192
|
+
// A plan-limit refusal is a deliberate per-file skip, never an error: the
|
|
2193
|
+
// file is counted, remembered for the end-of-pass notice, and paused.
|
|
2194
|
+
const emitPlanLimitSkip = (error, relativePath) => {
|
|
2195
|
+
const refusal = planLimitRefusalFromError(error);
|
|
2196
|
+
if (!refusal)
|
|
2129
2197
|
return false;
|
|
2130
2198
|
counters.filesSkipped++;
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2199
|
+
planLimitRefusal ??= refusal;
|
|
2200
|
+
if (!planLimitRefusedPaths.has(relativePath)) {
|
|
2201
|
+
planLimitRefusedPaths.add(relativePath);
|
|
2202
|
+
notePlanLimitedPath(relativePath);
|
|
2134
2203
|
}
|
|
2135
2204
|
return true;
|
|
2136
2205
|
};
|
|
2206
|
+
// Apply the pass's outcome to the pause record and report every file the
|
|
2207
|
+
// plan limit kept back in this pass, in ONE `plan-limit` event: files the
|
|
2208
|
+
// server refused now, and files skipped because an earlier refusal paused
|
|
2209
|
+
// them (`fromPause: true` when only the latter). A successful upload means
|
|
2210
|
+
// the server is accepting writes for this vault again, so earlier pauses
|
|
2211
|
+
// are dropped before this pass's refusals are recorded.
|
|
2212
|
+
const finishPlanLimitPass = () => {
|
|
2213
|
+
const now = planLimitPauseNow();
|
|
2214
|
+
// Read before clear(): the stored refusal describes the paused files.
|
|
2215
|
+
const storedRefusal = planLimitPauses.refusal;
|
|
2216
|
+
const pausesCleared = counters.filesUploaded > uploadedBeforePass;
|
|
2217
|
+
if (pausesCleared)
|
|
2218
|
+
planLimitPauses.clear();
|
|
2219
|
+
const refused = [...planLimitRefusedPaths];
|
|
2220
|
+
if (planLimitRefusal && refused.length > 0) {
|
|
2221
|
+
planLimitPauses.pause(refused, planLimitRefusal, now);
|
|
2222
|
+
}
|
|
2223
|
+
const pausedSkips = [...planLimitPausedSkips.keys()].filter((p) => !planLimitRefusedPaths.has(p));
|
|
2224
|
+
const refusal = planLimitRefusal ?? storedRefusal;
|
|
2225
|
+
if (refusal && refused.length + pausedSkips.length > 0) {
|
|
2226
|
+
counters.planLimit ??= refusal;
|
|
2227
|
+
// The earliest moment any of these files is retried. Paused files whose
|
|
2228
|
+
// pause was just cleared by a successful upload retry on the next pass.
|
|
2229
|
+
let retryAt = refused.length > 0 ? now + PLAN_LIMIT_PAUSE_RETRY_MS : Infinity;
|
|
2230
|
+
for (const p of pausedSkips) {
|
|
2231
|
+
retryAt = Math.min(retryAt, pausesCleared ? now : planLimitPausedSkips.get(p));
|
|
2232
|
+
}
|
|
2233
|
+
run.emit({
|
|
2234
|
+
type: "plan-limit",
|
|
2235
|
+
...refusal,
|
|
2236
|
+
upgradeUrl: refusal.upgradeUrl,
|
|
2237
|
+
count: refused.length + pausedSkips.length,
|
|
2238
|
+
paths: [...refused, ...pausedSkips].slice(0, PLAN_LIMITED_PATHS_CAP),
|
|
2239
|
+
pausedUntil: new Date(retryAt).toISOString(),
|
|
2240
|
+
fromPause: refused.length === 0,
|
|
2241
|
+
});
|
|
2242
|
+
}
|
|
2243
|
+
planLimitPauses.save(now);
|
|
2244
|
+
};
|
|
2137
2245
|
const settleFreshSkip = (item) => {
|
|
2138
2246
|
if (item.action === "refuse-server-owned") {
|
|
2139
2247
|
if (run.options.serverOwnedPathPolicy !== "skip") {
|
|
@@ -2782,7 +2890,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2782
2890
|
// full-journal write after every later PUT.
|
|
2783
2891
|
if (err instanceof JournalCheckpointError)
|
|
2784
2892
|
throw err;
|
|
2785
|
-
if (emitPlanLimitSkip(err))
|
|
2893
|
+
if (emitPlanLimitSkip(err, relativePath))
|
|
2786
2894
|
return;
|
|
2787
2895
|
if (isPreconditionFailed(err)) {
|
|
2788
2896
|
conflictPaths.push(relativePath);
|
|
@@ -2837,7 +2945,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2837
2945
|
}
|
|
2838
2946
|
if (retryErr instanceof JournalCheckpointError)
|
|
2839
2947
|
throw retryErr;
|
|
2840
|
-
if (emitPlanLimitSkip(retryErr))
|
|
2948
|
+
if (emitPlanLimitSkip(retryErr, relativePath))
|
|
2841
2949
|
return;
|
|
2842
2950
|
if (isPreconditionFailed(retryErr)) {
|
|
2843
2951
|
counters.filesSkipped++;
|
|
@@ -2925,7 +3033,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2925
3033
|
isRetryableIdentityRefusal(retryErr)) {
|
|
2926
3034
|
throw retryErr;
|
|
2927
3035
|
}
|
|
2928
|
-
if (emitPlanLimitSkip(retryErr))
|
|
3036
|
+
if (emitPlanLimitSkip(retryErr, relativePath))
|
|
2929
3037
|
return;
|
|
2930
3038
|
hadUploadFailure = true;
|
|
2931
3039
|
run.emit({
|
|
@@ -3056,6 +3164,20 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
3056
3164
|
skippedSinceCooperativeCheckpoint++;
|
|
3057
3165
|
continue;
|
|
3058
3166
|
}
|
|
3167
|
+
const pausedUntil = planLimitPausedUntil(item);
|
|
3168
|
+
if (pausedUntil !== undefined) {
|
|
3169
|
+
// Refused by the plan limit within the last hour: skip it without a
|
|
3170
|
+
// presign until the pause lapses, the admission check clears it, or
|
|
3171
|
+
// an upload to this vault succeeds. Reported at the end of the pass.
|
|
3172
|
+
queue.shift();
|
|
3173
|
+
counters.filesSkipped++;
|
|
3174
|
+
if (!planLimitPausedSkips.has(item.relativePath)) {
|
|
3175
|
+
planLimitPausedSkips.set(item.relativePath, pausedUntil);
|
|
3176
|
+
notePlanLimitedPath(item.relativePath);
|
|
3177
|
+
}
|
|
3178
|
+
skippedSinceCooperativeCheckpoint++;
|
|
3179
|
+
continue;
|
|
3180
|
+
}
|
|
3059
3181
|
// Reserve the file's CURRENT on-disk size, not the planned size: an
|
|
3060
3182
|
// active log/session file can grow between planning and upload, and
|
|
3061
3183
|
// uploadFile buffers the whole current body. A stale planned size would
|
|
@@ -3135,6 +3257,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
3135
3257
|
}
|
|
3136
3258
|
}
|
|
3137
3259
|
}
|
|
3260
|
+
finishPlanLimitPass();
|
|
3138
3261
|
return { aborted, abortFlightConflictPaths, workerErrors, hadUploadFailure };
|
|
3139
3262
|
}
|
|
3140
3263
|
/**
|
|
@@ -3946,6 +4069,9 @@ function buildShareResult(run, counters, filesRefusedStalePaths, conflictPaths,
|
|
|
3946
4069
|
linkedSubtreesNotShipped: [...run.linkedSubtreeSet],
|
|
3947
4070
|
conflictPaths,
|
|
3948
4071
|
pathResults,
|
|
4072
|
+
filesPlanLimited: counters.filesPlanLimited,
|
|
4073
|
+
planLimitedPaths: counters.planLimitedPaths,
|
|
4074
|
+
...(counters.planLimit ? { planLimit: counters.planLimit } : {}),
|
|
3949
4075
|
aborted,
|
|
3950
4076
|
};
|
|
3951
4077
|
}
|
|
@@ -3960,7 +4086,7 @@ function defaultConsoleLogger(event) {
|
|
|
3960
4086
|
}
|
|
3961
4087
|
}
|
|
3962
4088
|
else if (event.type === "plan-limit") {
|
|
3963
|
-
console.warn(
|
|
4089
|
+
console.warn(formatPlanLimitNotice(event));
|
|
3964
4090
|
}
|
|
3965
4091
|
else if (event.type === "progress") {
|
|
3966
4092
|
if (event.deleted) {
|