@gitroll/tacitt-cli 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-setup-Bpsi-BCv.mjs → agent-setup-BZbgLgHg.mjs} +2 -2
- package/dist/agent-setup-worker.mjs +5 -5
- package/dist/cli.mjs +6 -5
- package/dist/codex-title-worker.mjs +1 -1
- package/dist/configured-preview-worker.mjs +5 -5
- package/dist/configured-session-worker.mjs +5 -5
- package/dist/{frame-IeDOLy1o.mjs → frame-DGun31Uc.mjs} +1 -1
- package/dist/{heap-DiOlSa8T.mjs → heap-NDnGBXH6.mjs} +3 -3
- package/dist/inspection-worker.mjs +4 -4
- package/dist/{job-BII94L2c.mjs → job-BO0a67HQ.mjs} +383 -8
- package/dist/{locate-CBiw-CJK.mjs → locate-JYtFmKu-.mjs} +115 -3
- package/dist/{model-DGTsARtV.mjs → model-CmHypB0p.mjs} +1 -1
- package/dist/operation-executor.mjs +3 -3
- package/dist/preview-worker.mjs +1 -1
- package/dist/privacy-validator.mjs +1 -1
- package/dist/{query-CVqWNFYf.mjs → query-BZvNsP1u.mjs} +458 -29
- package/dist/{run-BGlf-W0M.mjs → run-DvRM-NR8.mjs} +4 -4
- package/dist/{src-CBTvOa44.mjs → src-C1SjCDx0.mjs} +21 -3
- package/dist/{src-D4nrfC2S.mjs → src-CQeUBG2Y.mjs} +6 -5
- package/dist/{src-37kIclGK.mjs → src-xidy0yF7.mjs} +4 -4
- package/dist/store-database-worker.mjs +1 -1
- package/dist/web/assets/index-Bbck2aOB.css +1 -0
- package/dist/web/assets/{index-D3g_ATU-.js → index-D0j-mvf1.js} +2 -2
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/skills/tacitt/SKILL.md +2 -2
- package/skills/tacitt/references/INDEX.md +11 -10
- package/skills/tacitt/references/commands.md +13 -0
- package/skills/tacitt/references/journey.md +1 -1
- package/skills/tacitt/references/remote-workers.md +46 -0
- package/skills/tacitt/references/send.md +4 -0
- package/skills/tacitt/scripts/privacy-validator.mjs +76 -3
- package/dist/web/assets/index-D5DEG5Ue.css +0 -1
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { $ as createCleanup, B as parallelismLimits, C as readOriginalSearchFields, E as checkReusableBundle, F as SessionWorkerError, G as processJourneyMetadataFields, H as privateJourneyDirectory, I as sessionWorkerFailure, K as staticMaskCategory, L as privateCollectionDirectory, M as readCollectionIndex, N as parseCollectionWorkspaceSummary, O as captureLogicalJourneySources, P as createSharedSessionPool, Q as removeNamedTemporarySpools, R as defaultParallelism, T as createCollectionArtifacts, U as readLogicalJourneyFinalMasks, W as readConfiguredOutputInfo, Z as createTemporary, _ as processJourneyMetadata, a as scanReviewFields, at as windowsOwnerOnly, c as readSessionScanRecords, g as readCapturedOriginalRows, i as buildWorkScanBatches, it as restrictToOwner, j as runConfiguredSessionJob, k as capturedJourneyScope, l as scanPreparedSession, m as openConfiguredUpload, n as verifyPreparedSessionSources, nt as makePrivateDirectory, o as createWorkPieces, ot as isWindowsAclFailure, p as configuredSessionUploads, q as readWorkspacePair, r as prepareSessionScans, rt as openPrivateFile, s as readSessionScanFields, st as windowsAclCodes, t as preparedScanConfiguration, v as readStaticSessionMasks, w as readConfiguredSearchFields, y as staticSessionJobs, z as gitSeedsProvider } from "./src-
|
|
2
|
-
import { Bt as sessionPeriodSchema, Dn as
|
|
3
|
-
import { a as mainTextChunks, c as previewInWorker, i as nearestSortingRepository, l as createNativeAdapters, n as createProjectEvidenceCollector, o as mainTextFields, r as sortingRepositoryId, s as textChunks, t as createHarnesses, u as createGitNameSeedProvider } from "./src-
|
|
4
|
-
import { $ as settingsQuerySchema, $r as packageCommandSchema, A as deviceProfileScopeSchema, B as validateInspectionBatch, Bn as journeyConfirmedHides, Br as hasCompleteWorkDescription, Bt as newJourneyWork, C as rebindReviewSubmit, Cr as privacyDecisionDigest, Ct as sendStartSchema, D as createAccount, Dr as hasCurrentStaticReview, E as staticallyHiddenFindings, Er as nativeRespondSchema, Et as obsoleteJourney, Fn as confirmedHideGroupIds, Fr as sendArtifactSchema, Gr as withReadingProgress, Hr as isReadingComplete, Ht as journeyContextQuerySchema, Ir as sendReceiptSchema, Jn as reviewCandidateResourceSchema, Jr as journeyFindingsSchema, Kn as workCorrectionBinding, L as createApplication, Ln as confirmedHideKinds, Lr as sendReplaceResultSchema, Lt as classificationPartition, M as readAccountAvatarUrl, Mr as agentSourceSchema, Mt as applyClassification, N as storedCredentialSchema, Nn as bTermMatcher, Nr as agentSourcesSchema, O as accountProfileSchema, Or as staticReviewDigest, Pr as journeySendSchema, Pt as journeyReviewStorageQuerySchema, Q as settingsBatchSchema, Qn as bReviewDigest, Qr as commandSchema, Qt as journeyResourceQuerySchema, R as inspectionCancelSchema, Rr as sendResolutionSchema, Rt as classificationWorks, S as rebindReviewOverlay, Sn as readConfirmedHideChange, Sr as assertJourneyPrivacyReady, St as sendPrepareSchema, T as guardedFindingText, Tn as termHideAdditions, Tr as nativeGetSchema, Tt as currentJourneyAdapters, U as inspectionQuerySchema, Un as retireWorkDescription, Ur as isSelectedWork, Vn as maskedHitsStale, Vr as isClassifying, Vt as reviewCompileSchema, Wn as workDecisionDigest, Xn as reviewRepairResourceSchema, Xr as journeyRenderInputSchema, Xt as journeyPolicyRespondSchema, Yn as reviewRepairInputSchema, Yr as journeyPreviewSchema, Yt as searchScopeDigest, Zr as journeyRenderSchema, _t as maximumTermsFileBytes, a as bCrossSegmentReviewSchema, ar as scanGitSeedsId, b as bReviewScope, bn as confirmedHideAdditions, br as journeyClassificationSessionsSchema, bt as sendActionSchema, c as reconstructBFields, cr as scanExclusionResourceSchema, ct as validateFailureLocation, d as selectedValueMembers, dn as sessionReviewInputSchema, dr as journeyInventoryQuerySchema, dt as manualUploadChoiceSchema, ei as selectionBatchSchema, er as planBRepair, et as readWorkspaceOutcomes, f as splitSelectorValues, fn as sessionReviewQuerySchema, ft as manualUploadPrepareSchema, g as changeJourney, gt as emptyTermsRevision, hn as sessionUsefulnessInputSchema, hr as emptyPreparationFacts, i as validateBCrossSegmentReview, ii as stateSchema, ir as scanSessionResourceSchema, j as profileUrlMatchesIdentity, k as deviceAuthorizationSchema, ln as sessionRereadInputSchema, lt as manualUploadActionSchema, m as hideScopeDigest, mt as manualUploadStartSchema, n as scanBatchEquivalenceDigest, nt as appendSensitiveTerms, o as bRereadDigest, oi as recommendParallelism, on as sessionReconcileInputSchema, or as scanGitSeedsResource, ot as artifactFailureDetailSchema, p as activeJourneyTerms, pt as manualUploadSchema, qn as reviewCandidateInputSchema, qr as journeyFindingImpactSchema, qt as journeySearchResultSchema, r as locateTermEvidence, ri as producerVersion, rn as reviewAttemptResourceSchema, rr as scanPreparationDigest, s as reconcileBSession, sr as verifiedScanGitSeeds, st as resolveFailureLocation, t as scanBatchContextDigest, ti as selectionSchema, tn as journeyPlaceSchema, vt as normalizeSensitiveTerms, w as reviewBatchReuse, wr as nativeEventsSchema, x as rebindReviewAlignment, xt as sendChoiceSchema, y as isGenericPublicTerm, yt as replaceSensitiveTermsSchema, z as inspectionStartSchema, zr as sendSettingsSchema, zt as retireScanGeneration } from "./src-
|
|
5
|
-
import { $ as checkVersion, A as resourceSelectionQuerySchema, B as termReuseQuerySchema, C as loadAcceptedReview, D as aggregateUsefulness, E as loadPrivateResource, F as validateUnitCandidate, G as requireActiveBatch, H as batchHeader, I as reuseQuerySchema, J as validateDatabase, K as initializeAndClaim, L as batchQuery, M as evaluateUnitEvidence, N as sameCandidateRequest, O as sessionUsefulnessRecommendation, P as validateCandidateAttempt, Q as validateState, R as isPrivateResourceKind, S as validateSessionBindings, T as loadBatch, U as createJourneyPayloadFiles, V as privateReviewHash, W as validateBatchBody, X as readBundleDirectory, Y as withDatabase, Z as readStoredState, _ as loadReconciliation, _t as isCoordinationBusy, a as decodeError, at as hasResetMarker, b as validatePreparationSelection, c as dropsAnchor, ct as privatePath, d as parseDelivery, dt as stateDirectory, et as schemaVersion, f as validateCandidate, ft as syncDirectory, g as loadPreparedBodies, gt as errorCode$1, h as loadPreparation, ht as StoreError, i as createExecutor, it as finishReset, j as inspectionQuerySchema$1, k as sessionQuery, l as replySchema, lt as readResetMarker, m as loadStatus, mt as withFileCheckTimings, n as releaseInheritedHeapFlags, nt as createDatabaseFile, o as ProtocolError, ot as inspectStateFiles, p as classificationJourneyCommit, pt as withStateSnapshot, q as ownership, r as storeHeapLimits, rt as databaseName, s as allowedReplies, st as present, tt as beginReset, u as operations, ut as recheckPrivatePath, v as loadRereadBodies, vt as isSqliteCorruption, w as loadAuthenticatedReview, x as validateSessionReconciliation, y as loadSessionBodies, z as privateResourceHeader } from "./heap-
|
|
6
|
-
import { _ as staticBaseProduction, a as writeJourneyOutput, c as mergeHideIndexTokens, f as writeJourneyBase, g as staticBaseInputs, h as staticSessions, l as packRenderHideIndex, m as saveStaticSession, o as createHideIndexTokens, p as readStaticResult, s as hideIndexTexts, t as journeyOutputJob, u as journeyBaseJob, v as prepareSourcePlan, y as workApproval } from "./job-
|
|
7
|
-
import { t as createAgentSetupPort } from "./agent-setup-
|
|
1
|
+
import { $ as createCleanup, B as parallelismLimits, C as readOriginalSearchFields, E as checkReusableBundle, F as SessionWorkerError, G as processJourneyMetadataFields, H as privateJourneyDirectory, I as sessionWorkerFailure, K as staticMaskCategory, L as privateCollectionDirectory, M as readCollectionIndex, N as parseCollectionWorkspaceSummary, O as captureLogicalJourneySources, P as createSharedSessionPool, Q as removeNamedTemporarySpools, R as defaultParallelism, T as createCollectionArtifacts, U as readLogicalJourneyFinalMasks, W as readConfiguredOutputInfo, Z as createTemporary, _ as processJourneyMetadata, a as scanReviewFields, at as windowsOwnerOnly, c as readSessionScanRecords, g as readCapturedOriginalRows, i as buildWorkScanBatches, it as restrictToOwner, j as runConfiguredSessionJob, k as capturedJourneyScope, l as scanPreparedSession, m as openConfiguredUpload, n as verifyPreparedSessionSources, nt as makePrivateDirectory, o as createWorkPieces, ot as isWindowsAclFailure, p as configuredSessionUploads, q as readWorkspacePair, r as prepareSessionScans, rt as openPrivateFile, s as readSessionScanFields, st as windowsAclCodes, t as preparedScanConfiguration, v as readStaticSessionMasks, w as readConfiguredSearchFields, y as staticSessionJobs, z as gitSeedsProvider } from "./src-CQeUBG2Y.mjs";
|
|
2
|
+
import { $t as safeField, Bt as sessionPeriodSchema, Dn as createStaticProcessor, F as bClassificationKey, Fn as entityDictionaryVersion, Ft as termTypeInfo, Gt as ownerProfileSchema, H as codePointLength, Ht as journeyProfileAddressActionSchema, K as utf16Offset, Kt as passportAddressSchema, N as bUnitFragments, Ot as privacyTermKey, Qt as safeCode, Sn as currentDetectorVersion, T as bLiteralTerms, Un as frameRecords, Ut as journeyProfileLinksActionSchema, V as bDigest, Wt as mergeOwnerProfile, Xt as ApplicationError, Zt as UnfinishedJourneyError, an as observeSource, ar as admitCustomTerm, b as validateBReview, c as textDigest, h as reviewFindingsDigest, ht as journeyDescribeSchema, ir as createEntityMatcher, jt as reviewTermsInputSchema, l as validateReview, n as compileBFindings, nn as reviewFamilies, or as admitGitName, qt as profileHasChoices, r as reviewBatchChunks, s as reviewSubmitSchema, t as locateTerms, tn as familySelected, z as bAnchorKey, zt as filterInventoryByPeriod } from "./locate-JYtFmKu-.mjs";
|
|
3
|
+
import { a as mainTextChunks, c as previewInWorker, i as nearestSortingRepository, l as createNativeAdapters, n as createProjectEvidenceCollector, o as mainTextFields, r as sortingRepositoryId, s as textChunks, t as createHarnesses, u as createGitNameSeedProvider } from "./src-xidy0yF7.mjs";
|
|
4
|
+
import { $ as settingsQuerySchema, $r as packageCommandSchema, A as deviceProfileScopeSchema, B as validateInspectionBatch, Bn as journeyConfirmedHides, Br as hasCompleteWorkDescription, Bt as newJourneyWork, C as rebindReviewSubmit, Cr as privacyDecisionDigest, Ct as sendStartSchema, D as createAccount, Dr as hasCurrentStaticReview, E as staticallyHiddenFindings, Er as nativeRespondSchema, Et as obsoleteJourney, Fn as confirmedHideGroupIds, Fr as sendArtifactSchema, Gr as withReadingProgress, Hr as isReadingComplete, Ht as journeyContextQuerySchema, Ir as sendReceiptSchema, Jn as reviewCandidateResourceSchema, Jr as journeyFindingsSchema, Kn as workCorrectionBinding, L as createApplication, Ln as confirmedHideKinds, Lr as sendReplaceResultSchema, Lt as classificationPartition, M as readAccountAvatarUrl, Mr as agentSourceSchema, Mt as applyClassification, N as storedCredentialSchema, Nn as bTermMatcher, Nr as agentSourcesSchema, O as accountProfileSchema, Or as staticReviewDigest, Pr as journeySendSchema, Pt as journeyReviewStorageQuerySchema, Q as settingsBatchSchema, Qn as bReviewDigest, Qr as commandSchema, Qt as journeyResourceQuerySchema, R as inspectionCancelSchema, Rr as sendResolutionSchema, Rt as classificationWorks, S as rebindReviewOverlay, Sn as readConfirmedHideChange, Sr as assertJourneyPrivacyReady, St as sendPrepareSchema, T as guardedFindingText, Tn as termHideAdditions, Tr as nativeGetSchema, Tt as currentJourneyAdapters, U as inspectionQuerySchema, Un as retireWorkDescription, Ur as isSelectedWork, Vn as maskedHitsStale, Vr as isClassifying, Vt as reviewCompileSchema, Wn as workDecisionDigest, Xn as reviewRepairResourceSchema, Xr as journeyRenderInputSchema, Xt as journeyPolicyRespondSchema, Yn as reviewRepairInputSchema, Yr as journeyPreviewSchema, Yt as searchScopeDigest, Zr as journeyRenderSchema, _t as maximumTermsFileBytes, a as bCrossSegmentReviewSchema, ar as scanGitSeedsId, b as bReviewScope, bn as confirmedHideAdditions, br as journeyClassificationSessionsSchema, bt as sendActionSchema, c as reconstructBFields, cr as scanExclusionResourceSchema, ct as validateFailureLocation, d as selectedValueMembers, dn as sessionReviewInputSchema, dr as journeyInventoryQuerySchema, dt as manualUploadChoiceSchema, ei as selectionBatchSchema, er as planBRepair, et as readWorkspaceOutcomes, f as splitSelectorValues, fn as sessionReviewQuerySchema, ft as manualUploadPrepareSchema, g as changeJourney, gt as emptyTermsRevision, hn as sessionUsefulnessInputSchema, hr as emptyPreparationFacts, i as validateBCrossSegmentReview, ii as stateSchema, ir as scanSessionResourceSchema, j as profileUrlMatchesIdentity, k as deviceAuthorizationSchema, ln as sessionRereadInputSchema, lt as manualUploadActionSchema, m as hideScopeDigest, mt as manualUploadStartSchema, n as scanBatchEquivalenceDigest, nt as appendSensitiveTerms, o as bRereadDigest, oi as recommendParallelism, on as sessionReconcileInputSchema, or as scanGitSeedsResource, ot as artifactFailureDetailSchema, p as activeJourneyTerms, pt as manualUploadSchema, qn as reviewCandidateInputSchema, qr as journeyFindingImpactSchema, qt as journeySearchResultSchema, r as locateTermEvidence, ri as producerVersion, rn as reviewAttemptResourceSchema, rr as scanPreparationDigest, s as reconcileBSession, sr as verifiedScanGitSeeds, st as resolveFailureLocation, t as scanBatchContextDigest, ti as selectionSchema, tn as journeyPlaceSchema, vt as normalizeSensitiveTerms, w as reviewBatchReuse, wr as nativeEventsSchema, x as rebindReviewAlignment, xt as sendChoiceSchema, y as isGenericPublicTerm, yt as replaceSensitiveTermsSchema, z as inspectionStartSchema, zr as sendSettingsSchema, zt as retireScanGeneration } from "./src-C1SjCDx0.mjs";
|
|
5
|
+
import { $ as checkVersion, A as resourceSelectionQuerySchema, B as termReuseQuerySchema, C as loadAcceptedReview, D as aggregateUsefulness, E as loadPrivateResource, F as validateUnitCandidate, G as requireActiveBatch, H as batchHeader, I as reuseQuerySchema, J as validateDatabase, K as initializeAndClaim, L as batchQuery, M as evaluateUnitEvidence, N as sameCandidateRequest, O as sessionUsefulnessRecommendation, P as validateCandidateAttempt, Q as validateState, R as isPrivateResourceKind, S as validateSessionBindings, T as loadBatch, U as createJourneyPayloadFiles, V as privateReviewHash, W as validateBatchBody, X as readBundleDirectory, Y as withDatabase, Z as readStoredState, _ as loadReconciliation, _t as isCoordinationBusy, a as decodeError, at as hasResetMarker, b as validatePreparationSelection, c as dropsAnchor, ct as privatePath, d as parseDelivery, dt as stateDirectory, et as schemaVersion, f as validateCandidate, ft as syncDirectory, g as loadPreparedBodies, gt as errorCode$1, h as loadPreparation, ht as StoreError, i as createExecutor, it as finishReset, j as inspectionQuerySchema$1, k as sessionQuery, l as replySchema, lt as readResetMarker, m as loadStatus, mt as withFileCheckTimings, n as releaseInheritedHeapFlags, nt as createDatabaseFile, o as ProtocolError, ot as inspectStateFiles, p as classificationJourneyCommit, pt as withStateSnapshot, q as ownership, r as storeHeapLimits, rt as databaseName, s as allowedReplies, st as present, tt as beginReset, u as operations, ut as recheckPrivatePath, v as loadRereadBodies, vt as isSqliteCorruption, w as loadAuthenticatedReview, x as validateSessionReconciliation, y as loadSessionBodies, z as privateResourceHeader } from "./heap-NDnGBXH6.mjs";
|
|
6
|
+
import { C as journeyDirectory, S as saveRemoteState, _ as staticBaseProduction, a as writeJourneyOutput, b as isRemoteImport, c as mergeHideIndexTokens, f as writeJourneyBase, g as staticBaseInputs, h as staticSessions, l as packRenderHideIndex, m as saveStaticSession, o as createHideIndexTokens, p as readStaticResult, s as hideIndexTexts, t as journeyOutputJob, u as journeyBaseJob, v as prepareSourcePlan, w as collectRemoteWorkers, x as readRemoteState, y as workApproval } from "./job-BO0a67HQ.mjs";
|
|
7
|
+
import { t as createAgentSetupPort } from "./agent-setup-BZbgLgHg.mjs";
|
|
8
8
|
import { t as workerMessageSchema } from "./messages-D3m3bhva.mjs";
|
|
9
9
|
import { constants, write } from "node:fs";
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
import { copyFile, link, lstat, mkdir, mkdtemp, open, opendir, readFile, readdir, realpath, rename, rm, unlink, writeFile } from "node:fs/promises";
|
|
12
12
|
import { execFile, spawn } from "node:child_process";
|
|
13
|
-
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
13
|
+
import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
|
|
14
|
+
import { createInterface } from "node:readline";
|
|
14
15
|
import { Writable } from "node:stream";
|
|
15
16
|
import { parseArgs, promisify, types } from "node:util";
|
|
16
17
|
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
@@ -27,6 +28,7 @@ import { pipeline } from "node:stream/promises";
|
|
|
27
28
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
28
29
|
import { DatabaseSync } from "node:sqlite";
|
|
29
30
|
import { Worker } from "node:worker_threads";
|
|
31
|
+
import { parse } from "shell-quote";
|
|
30
32
|
import { rgPath } from "@vscode/ripgrep";
|
|
31
33
|
import { pino } from "pino";
|
|
32
34
|
import { SeverityNumber } from "@opentelemetry/api-logs";
|
|
@@ -858,7 +860,9 @@ const nativePanelRespondSchema = z.object({
|
|
|
858
860
|
z.object({
|
|
859
861
|
kind: z.literal("retry-work"),
|
|
860
862
|
workId: z.uuid()
|
|
861
|
-
}).strict()
|
|
863
|
+
}).strict(),
|
|
864
|
+
journeyProfileAddressActionSchema,
|
|
865
|
+
journeyProfileLinksActionSchema
|
|
862
866
|
])
|
|
863
867
|
}).strict();
|
|
864
868
|
function createRouter(application, account, stopping, delivery, nativeInspection, agentPresence) {
|
|
@@ -932,7 +936,10 @@ function createRouter(application, account, stopping, delivery, nativeInspection
|
|
|
932
936
|
pause: t.procedure.input(sendActionSchema).mutation(({ input }) => sending().pause(input)),
|
|
933
937
|
resume: t.procedure.input(sendActionSchema).mutation(({ input }) => sending().resume(input)),
|
|
934
938
|
withdraw: t.procedure.input(sendActionSchema).mutation(({ input }) => sending().withdraw(input)),
|
|
935
|
-
advance: t.procedure.input(sendAddress).mutation(({ input }) => sending().advance(input, stopping))
|
|
939
|
+
advance: t.procedure.input(sendAddress).mutation(({ input }) => sending().advance(input, stopping)),
|
|
940
|
+
ownerProfile: t.procedure.query(({ signal }) => sending().ownerProfile(signal ?? stopping)),
|
|
941
|
+
addressTaken: t.procedure.input(z.object({ address: passportAddressSchema }).strict()).query(({ input, signal }) => sending().addressTaken(input, signal ?? stopping)),
|
|
942
|
+
saveSentProfile: t.procedure.input(z.object({ journeyId: z.uuid() }).strict()).mutation(({ input }) => sending().saveSentProfile(input, stopping))
|
|
936
943
|
}),
|
|
937
944
|
manualUpload: t.router({
|
|
938
945
|
get: t.procedure.input(z.object({ uploadId: z.uuid().optional() }).strict()).query(({ input }) => uploading().get(input.uploadId)),
|
|
@@ -5345,6 +5352,7 @@ const businessCommands = [
|
|
|
5345
5352
|
"send.resume",
|
|
5346
5353
|
"send.advance",
|
|
5347
5354
|
"journey.start",
|
|
5355
|
+
"journey.remoteWorkers",
|
|
5348
5356
|
"journey.serve",
|
|
5349
5357
|
"journey.get",
|
|
5350
5358
|
"journey.groupItems",
|
|
@@ -5634,6 +5642,334 @@ function helpText(source = sourceCheckout) {
|
|
|
5634
5642
|
return source ? fullHelp : fullHelp.replace(/^ {2}--dev .*\n/m, "");
|
|
5635
5643
|
}
|
|
5636
5644
|
//#endregion
|
|
5645
|
+
//#region apps/cli/src/remote/dispatch.ts
|
|
5646
|
+
function balancedQuotes(command) {
|
|
5647
|
+
let quote = "";
|
|
5648
|
+
let escaped = false;
|
|
5649
|
+
for (const character of command) {
|
|
5650
|
+
if (escaped) {
|
|
5651
|
+
escaped = false;
|
|
5652
|
+
continue;
|
|
5653
|
+
}
|
|
5654
|
+
if (character === "\\" && quote !== "'") escaped = true;
|
|
5655
|
+
else if (quote === character) quote = "";
|
|
5656
|
+
else if (!quote && (character === "'" || character === "\"")) quote = character;
|
|
5657
|
+
}
|
|
5658
|
+
return !quote && !escaped;
|
|
5659
|
+
}
|
|
5660
|
+
/** Parse inert simple commands. Expansions and unsupported compound syntax fail closed. */
|
|
5661
|
+
function commands$1(command) {
|
|
5662
|
+
if (Buffer.byteLength(command) > 65536 || /`|\$\(|[\0\r]/u.test(command) || !balancedQuotes(command)) return [];
|
|
5663
|
+
try {
|
|
5664
|
+
const segments = [[]];
|
|
5665
|
+
let redirect = false;
|
|
5666
|
+
for (const token of parse(command.replaceAll("\n", ";"), () => "\0")) if (typeof token === "string") {
|
|
5667
|
+
if (token.includes("\0")) return [];
|
|
5668
|
+
if (redirect) redirect = false;
|
|
5669
|
+
else segments.at(-1)?.push(token);
|
|
5670
|
+
} else if ("comment" in token) continue;
|
|
5671
|
+
else if ("op" in token && [
|
|
5672
|
+
">",
|
|
5673
|
+
">>",
|
|
5674
|
+
"<",
|
|
5675
|
+
">&",
|
|
5676
|
+
"<&"
|
|
5677
|
+
].includes(token.op)) {
|
|
5678
|
+
if (redirect) return [];
|
|
5679
|
+
redirect = true;
|
|
5680
|
+
} else if ("op" in token && [
|
|
5681
|
+
";",
|
|
5682
|
+
"&&",
|
|
5683
|
+
"||",
|
|
5684
|
+
"|",
|
|
5685
|
+
"&"
|
|
5686
|
+
].includes(token.op)) segments.push([]);
|
|
5687
|
+
else return [];
|
|
5688
|
+
return redirect ? [] : segments.filter((words) => words.length > 0);
|
|
5689
|
+
} catch {
|
|
5690
|
+
return [];
|
|
5691
|
+
}
|
|
5692
|
+
}
|
|
5693
|
+
function agent(words) {
|
|
5694
|
+
const executable = posix.basename(words[0] ?? "");
|
|
5695
|
+
if (words.some((word) => [
|
|
5696
|
+
"--help",
|
|
5697
|
+
"-h",
|
|
5698
|
+
"--version"
|
|
5699
|
+
].includes(word))) return null;
|
|
5700
|
+
if (executable === "codex" && words[1] === "exec") return "codex";
|
|
5701
|
+
if (executable === "claude" && words.slice(1).some((word) => word === "-p" || word === "--print")) return "claude";
|
|
5702
|
+
return null;
|
|
5703
|
+
}
|
|
5704
|
+
const validHost = (host) => /^(?:[a-zA-Z0-9_][a-zA-Z0-9_.-]*@)?(?:[a-zA-Z0-9_][a-zA-Z0-9_.-]*|\[[a-fA-F0-9:]+\])$/u.test(host);
|
|
5705
|
+
/** Consent and import identity include every retained connection selector. */
|
|
5706
|
+
function endpoint(host, transport, args) {
|
|
5707
|
+
return transport === "ssh" && args.length === 1 ? host : `${host} (${transport}: ${args.join(" ")})`;
|
|
5708
|
+
}
|
|
5709
|
+
function ssh(words) {
|
|
5710
|
+
const args = [];
|
|
5711
|
+
let index = 1;
|
|
5712
|
+
for (; index < words.length; index++) {
|
|
5713
|
+
const word = words[index] ?? "";
|
|
5714
|
+
if (word === "--") {
|
|
5715
|
+
index++;
|
|
5716
|
+
break;
|
|
5717
|
+
}
|
|
5718
|
+
if (!word.startsWith("-")) break;
|
|
5719
|
+
if (word === "--help" || /^-[^-]*[NVGQOW]/u.test(word)) return null;
|
|
5720
|
+
if (/^-[pLlIiFJoObcDEeRSwWQ]/u.test(word)) {
|
|
5721
|
+
const flag = word.slice(0, 2);
|
|
5722
|
+
const value = word.length > 2 ? word.slice(2) : words[++index];
|
|
5723
|
+
if (!value) return null;
|
|
5724
|
+
if (flag === "-p" && /^\d{1,5}$/u.test(value)) args.push(flag, value);
|
|
5725
|
+
if (flag === "-l" && /^[a-zA-Z0-9_.-]+$/u.test(value)) args.push(flag, value);
|
|
5726
|
+
} else if (!/^-[46AaCfKkMnqsTtVvXxYy]+$/u.test(word)) return null;
|
|
5727
|
+
}
|
|
5728
|
+
const host = words[index];
|
|
5729
|
+
if (!host || !validHost(host) || index + 1 >= words.length) return null;
|
|
5730
|
+
return {
|
|
5731
|
+
host,
|
|
5732
|
+
transport: "ssh",
|
|
5733
|
+
args: [...args, host],
|
|
5734
|
+
command: words.slice(index + 1).join(" ")
|
|
5735
|
+
};
|
|
5736
|
+
}
|
|
5737
|
+
function gcloud(words) {
|
|
5738
|
+
if (words[1] !== "compute" || words[2] !== "ssh") return null;
|
|
5739
|
+
let host;
|
|
5740
|
+
let command;
|
|
5741
|
+
const selectors = [];
|
|
5742
|
+
for (let index = 3; index < words.length; index++) {
|
|
5743
|
+
const word = words[index] ?? "";
|
|
5744
|
+
if (word === "--help" || word === "-h" || word === "--dry-run") return null;
|
|
5745
|
+
if (word === "--command" || word.startsWith("--command=")) command = word === "--command" ? words[++index] : word.slice(10);
|
|
5746
|
+
else if (["--zone", "--project"].some((flag) => word === flag || word.startsWith(`${flag}=`))) {
|
|
5747
|
+
const separator = word.indexOf("=");
|
|
5748
|
+
const flag = separator === -1 ? word : word.slice(0, separator);
|
|
5749
|
+
const value = separator === -1 ? words[++index] : word.slice(separator + 1);
|
|
5750
|
+
if (!value || !/^[a-zA-Z0-9_.:-]+$/u.test(value)) return null;
|
|
5751
|
+
selectors.push(`${flag}=${value}`);
|
|
5752
|
+
} else if (word === "--tunnel-through-iap" || word === "--internal-ip") selectors.push(word);
|
|
5753
|
+
else if (word === "--quiet" || word === "-q") continue;
|
|
5754
|
+
else if (!word.startsWith("-") && !host) host = word;
|
|
5755
|
+
else return null;
|
|
5756
|
+
}
|
|
5757
|
+
if (!host || !validHost(host) || !command) return null;
|
|
5758
|
+
return {
|
|
5759
|
+
host,
|
|
5760
|
+
transport: "gcloud",
|
|
5761
|
+
args: [host, ...selectors],
|
|
5762
|
+
command
|
|
5763
|
+
};
|
|
5764
|
+
}
|
|
5765
|
+
/** Matches executables at shell command positions, never mentions in prose or other commands. */
|
|
5766
|
+
function parseRemoteDispatch(command) {
|
|
5767
|
+
return commands$1(command).flatMap((words) => {
|
|
5768
|
+
const executable = posix.basename(words[0] ?? "");
|
|
5769
|
+
const remote = executable === "ssh" ? ssh(words) : executable === "gcloud" ? gcloud(words) : null;
|
|
5770
|
+
if (!remote) return [];
|
|
5771
|
+
return [...new Set(commands$1(remote.command).map(agent))].flatMap((harness) => harness ? [{
|
|
5772
|
+
host: endpoint(remote.host, remote.transport, remote.args),
|
|
5773
|
+
harness,
|
|
5774
|
+
transport: remote.transport,
|
|
5775
|
+
args: remote.args
|
|
5776
|
+
}] : []);
|
|
5777
|
+
});
|
|
5778
|
+
}
|
|
5779
|
+
//#endregion
|
|
5780
|
+
//#region apps/cli/src/remote/scan.ts
|
|
5781
|
+
function object(value) {
|
|
5782
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5783
|
+
}
|
|
5784
|
+
function timestamp(value) {
|
|
5785
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value)) ? new Date(value).toISOString() : null;
|
|
5786
|
+
}
|
|
5787
|
+
function commands(row) {
|
|
5788
|
+
const payload = row["payload"];
|
|
5789
|
+
if (row["type"] === "response_item" && object(payload) && payload["type"] === "function_call" && typeof payload["name"] === "string" && [
|
|
5790
|
+
"exec_command",
|
|
5791
|
+
"shell_command",
|
|
5792
|
+
"shell"
|
|
5793
|
+
].includes(payload["name"])) {
|
|
5794
|
+
let args = payload["arguments"];
|
|
5795
|
+
if (typeof args === "string") try {
|
|
5796
|
+
args = JSON.parse(args);
|
|
5797
|
+
} catch {
|
|
5798
|
+
return [];
|
|
5799
|
+
}
|
|
5800
|
+
if (!object(args)) return [];
|
|
5801
|
+
const command = args["cmd"] ?? args["command"];
|
|
5802
|
+
return typeof command === "string" ? [{
|
|
5803
|
+
id: typeof payload["call_id"] === "string" ? payload["call_id"] : "",
|
|
5804
|
+
command
|
|
5805
|
+
}] : [];
|
|
5806
|
+
}
|
|
5807
|
+
const message = row["message"];
|
|
5808
|
+
if (row["type"] !== "assistant" || !object(message) || !Array.isArray(message["content"])) return [];
|
|
5809
|
+
return message["content"].flatMap((block) => {
|
|
5810
|
+
if (!object(block) || block["type"] !== "tool_use" || block["name"] !== "Bash" || !object(block["input"]) || typeof block["input"]["command"] !== "string") return [];
|
|
5811
|
+
return [{
|
|
5812
|
+
id: typeof block["id"] === "string" ? block["id"] : "",
|
|
5813
|
+
command: block["input"]["command"]
|
|
5814
|
+
}];
|
|
5815
|
+
});
|
|
5816
|
+
}
|
|
5817
|
+
function resultIds(row) {
|
|
5818
|
+
const payload = row["payload"];
|
|
5819
|
+
if (object(payload) && payload["type"] === "function_call_output" && typeof payload["call_id"] === "string") return [payload["call_id"]];
|
|
5820
|
+
const message = row["message"];
|
|
5821
|
+
if (!object(message) || !Array.isArray(message["content"])) return [];
|
|
5822
|
+
return message["content"].flatMap((block) => object(block) && block["type"] === "tool_result" && typeof block["tool_use_id"] === "string" ? [block["tool_use_id"]] : []);
|
|
5823
|
+
}
|
|
5824
|
+
/** Tool executable positions only. Source bytes stay inside this deterministic CLI scanner. */
|
|
5825
|
+
async function scanRemoteDispatches(sessions, signal) {
|
|
5826
|
+
const windows = [];
|
|
5827
|
+
for (const session of sessions) {
|
|
5828
|
+
const pending = /* @__PURE__ */ new Map();
|
|
5829
|
+
for (const part of session.parts) {
|
|
5830
|
+
signal.throwIfAborted();
|
|
5831
|
+
if (part.representation !== "jsonl") throw new Error("REMOTE_SOURCE_FORMAT_UNSUPPORTED");
|
|
5832
|
+
const file = await open(part.path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
5833
|
+
try {
|
|
5834
|
+
const before = await file.stat({ bigint: true });
|
|
5835
|
+
if (String(before.dev) !== part.snapshot.dev || String(before.ino) !== part.snapshot.ino || before.size !== BigInt(part.snapshot.size) || String(before.mtimeNs) !== part.snapshot.mtimeNs || String(before.ctimeNs) !== part.snapshot.ctimeNs) throw new Error("REMOTE_SOURCE_CHANGED");
|
|
5836
|
+
if (!part.snapshot.size) continue;
|
|
5837
|
+
const stream = file.createReadStream({
|
|
5838
|
+
autoClose: false,
|
|
5839
|
+
start: 0,
|
|
5840
|
+
end: part.snapshot.size - 1,
|
|
5841
|
+
signal
|
|
5842
|
+
});
|
|
5843
|
+
const lines = createInterface({
|
|
5844
|
+
input: stream,
|
|
5845
|
+
crlfDelay: Infinity
|
|
5846
|
+
});
|
|
5847
|
+
try {
|
|
5848
|
+
for await (const line of lines) {
|
|
5849
|
+
signal.throwIfAborted();
|
|
5850
|
+
if (line.length > 16777216) throw new Error("REMOTE_SOURCE_RECORD_TOO_LARGE");
|
|
5851
|
+
if (!line.trim()) continue;
|
|
5852
|
+
const row = JSON.parse(line);
|
|
5853
|
+
if (!object(row)) continue;
|
|
5854
|
+
const at = timestamp(row["timestamp"]);
|
|
5855
|
+
if (!at) continue;
|
|
5856
|
+
for (const id of resultIds(row)) {
|
|
5857
|
+
for (const window of pending.get(id) ?? []) if (at >= window.start) window.end = at;
|
|
5858
|
+
pending.delete(id);
|
|
5859
|
+
}
|
|
5860
|
+
for (const command of commands(row)) {
|
|
5861
|
+
const end = timestamp(session.lastInteractionAt);
|
|
5862
|
+
const found = parseRemoteDispatch(command.command).map((dispatch) => ({
|
|
5863
|
+
...dispatch,
|
|
5864
|
+
sourceSessionId: session.id,
|
|
5865
|
+
start: at,
|
|
5866
|
+
end: end && end >= at ? end : at
|
|
5867
|
+
}));
|
|
5868
|
+
windows.push(...found);
|
|
5869
|
+
pending.set(command.id, found);
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
const after = await file.stat({ bigint: true });
|
|
5873
|
+
if (after.mtimeNs !== before.mtimeNs || after.size !== before.size) throw new Error("REMOTE_SOURCE_CHANGED");
|
|
5874
|
+
} finally {
|
|
5875
|
+
lines.close();
|
|
5876
|
+
stream.destroy();
|
|
5877
|
+
}
|
|
5878
|
+
} finally {
|
|
5879
|
+
await file.close();
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
return windows;
|
|
5884
|
+
}
|
|
5885
|
+
//#endregion
|
|
5886
|
+
//#region apps/cli/src/remote/preflight.ts
|
|
5887
|
+
const inputSchema = z.object({
|
|
5888
|
+
journeyId: z.uuid(),
|
|
5889
|
+
confirmations: z.record(z.string(), z.boolean()).optional()
|
|
5890
|
+
}).strict();
|
|
5891
|
+
function createRemotePreflight(options) {
|
|
5892
|
+
return async (value, signal = new AbortController().signal) => {
|
|
5893
|
+
const input = inputSchema.parse(value);
|
|
5894
|
+
const current = await options.storage.current(input.journeyId);
|
|
5895
|
+
if (!current?.consent) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
5896
|
+
if (current.phase === "paused") throw new ApplicationError("OPERATION_CANCELED");
|
|
5897
|
+
if (current.snapshotId) return {
|
|
5898
|
+
hosts: [],
|
|
5899
|
+
copied: 0,
|
|
5900
|
+
failures: [],
|
|
5901
|
+
skipped: "already-frozen"
|
|
5902
|
+
};
|
|
5903
|
+
const lease = await options.execution.tryAcquire("workflow");
|
|
5904
|
+
if (!lease) throw new ApplicationError("DISCOVERY_BUSY");
|
|
5905
|
+
try {
|
|
5906
|
+
const admitted = await options.storage.current(input.journeyId);
|
|
5907
|
+
if (!admitted?.consent || admitted.phase === "paused") throw new ApplicationError("OPERATION_CANCELED");
|
|
5908
|
+
if (admitted.snapshotId) return {
|
|
5909
|
+
hosts: [],
|
|
5910
|
+
copied: 0,
|
|
5911
|
+
failures: [],
|
|
5912
|
+
skipped: "already-frozen"
|
|
5913
|
+
};
|
|
5914
|
+
let state = await readRemoteState(options.stateDir, input.journeyId);
|
|
5915
|
+
if (!state) {
|
|
5916
|
+
const discovered = await options.harnesses.discover(signal);
|
|
5917
|
+
if (!discovered.complete) throw new ApplicationError("SCOPE_NOT_READY");
|
|
5918
|
+
const inventory = filterInventoryByPeriod(discovered, current.period ?? {});
|
|
5919
|
+
const families = reviewFamilies(inventory);
|
|
5920
|
+
const sessions = inventory.sessions.filter((session) => familySelected(inventory, families, session) && !session.warnings.includes("NON_INTERACTIVE_LAUNCH") && session.parts.every((part) => !isRemoteImport(part.path)));
|
|
5921
|
+
state = {
|
|
5922
|
+
windows: [],
|
|
5923
|
+
decisions: {},
|
|
5924
|
+
parents: Object.fromEntries(sessions.map((session) => [session.id, session.sourceKey])),
|
|
5925
|
+
copied: [],
|
|
5926
|
+
failures: []
|
|
5927
|
+
};
|
|
5928
|
+
for (const session of sessions) try {
|
|
5929
|
+
state.windows.push(...await scanRemoteDispatches([session], signal));
|
|
5930
|
+
} catch (error) {
|
|
5931
|
+
signal.throwIfAborted();
|
|
5932
|
+
options.reportFailure(error);
|
|
5933
|
+
state.failures.push("source-scan");
|
|
5934
|
+
}
|
|
5935
|
+
await saveRemoteState(options.stateDir, input.journeyId, state);
|
|
5936
|
+
}
|
|
5937
|
+
const decisions = input.confirmations ?? {};
|
|
5938
|
+
const known = new Set(state.windows.map((window) => window.host));
|
|
5939
|
+
if (Object.keys(decisions).some((host) => !known.has(host))) throw new ApplicationError("INVALID_ARGUMENTS");
|
|
5940
|
+
const fresh = {};
|
|
5941
|
+
for (const [host, allow] of Object.entries(decisions)) {
|
|
5942
|
+
if (Object.hasOwn(state.decisions, host)) continue;
|
|
5943
|
+
fresh[host] = allow;
|
|
5944
|
+
state.decisions[host] = allow;
|
|
5945
|
+
}
|
|
5946
|
+
await saveRemoteState(options.stateDir, input.journeyId, state);
|
|
5947
|
+
if (Object.keys(fresh).length) {
|
|
5948
|
+
const collected = await collectRemoteWorkers(state.windows, fresh, options.home, options.transport, (_host, error) => options.reportFailure(new Error("REMOTE_COLLECTION_FAILED", { cause: error })), options.roots);
|
|
5949
|
+
state.copied.push(...collected.copied);
|
|
5950
|
+
state.failures.push(...collected.failures);
|
|
5951
|
+
await saveRemoteState(options.stateDir, input.journeyId, state);
|
|
5952
|
+
}
|
|
5953
|
+
return result(state);
|
|
5954
|
+
} finally {
|
|
5955
|
+
await lease.release();
|
|
5956
|
+
}
|
|
5957
|
+
};
|
|
5958
|
+
}
|
|
5959
|
+
function result(state) {
|
|
5960
|
+
return {
|
|
5961
|
+
hosts: [...new Set(state.windows.map((window) => window.host))].filter((host) => !Object.hasOwn(state.decisions, host)).map((host) => ({
|
|
5962
|
+
host,
|
|
5963
|
+
windows: state.windows.filter((window) => window.host === host).map(({ start, end }) => ({
|
|
5964
|
+
start,
|
|
5965
|
+
end
|
|
5966
|
+
}))
|
|
5967
|
+
})),
|
|
5968
|
+
copied: state.copied.length,
|
|
5969
|
+
failures: state.failures
|
|
5970
|
+
};
|
|
5971
|
+
}
|
|
5972
|
+
//#endregion
|
|
5637
5973
|
//#region apps/cli/src/journey/confirmed-hides.ts
|
|
5638
5974
|
/** The Work's explicit exception values; an occurrence inside one stays visible (ADR 0069). */
|
|
5639
5975
|
const workExceptions = (state, workId) => state.exceptions.filter((item) => item.workId === workId).map((item) => item.value);
|
|
@@ -7193,22 +7529,6 @@ async function prepareStaticWork(options) {
|
|
|
7193
7529
|
});
|
|
7194
7530
|
}
|
|
7195
7531
|
//#endregion
|
|
7196
|
-
//#region apps/cli/src/journey/directory.ts
|
|
7197
|
-
async function journeyDirectory(stateDir, journeyId) {
|
|
7198
|
-
let path = stateDir;
|
|
7199
|
-
for (const name of ["journeys", journeyId]) {
|
|
7200
|
-
path = join(path, name);
|
|
7201
|
-
try {
|
|
7202
|
-
await makePrivateDirectory(path);
|
|
7203
|
-
} catch (cause) {
|
|
7204
|
-
if (!(cause instanceof Error && "code" in cause && cause.code === "EEXIST")) throw cause;
|
|
7205
|
-
}
|
|
7206
|
-
const stat = await lstat(path, { bigint: true });
|
|
7207
|
-
if (!stat.isDirectory() || stat.isSymbolicLink() || await realpath(path) !== path || (process.platform === "win32" ? !await windowsOwnerOnly(path, "directory") : stat.uid !== BigInt(process.getuid?.() ?? -1) || (stat.mode & 63n) !== 0n)) throw new ApplicationError("UNSAFE_STATE_PATH");
|
|
7208
|
-
}
|
|
7209
|
-
return path;
|
|
7210
|
-
}
|
|
7211
|
-
//#endregion
|
|
7212
7532
|
//#region apps/cli/src/journey/observe.ts
|
|
7213
7533
|
/** Observe whole-journey pause while a single large Work is still being processed. */
|
|
7214
7534
|
function observeJourneyPause(storage, journeyId, processing, onFailure, requireConfirmedScope = false) {
|
|
@@ -7396,7 +7716,7 @@ function createJourneyPreparation(options) {
|
|
|
7396
7716
|
revision: "empty",
|
|
7397
7717
|
terms: []
|
|
7398
7718
|
};
|
|
7399
|
-
const plan = await prepareSourcePlan(storage, options.harnesses, journeyId, terms, abort.signal, current.period);
|
|
7719
|
+
const plan = await prepareSourcePlan(storage, options.harnesses, journeyId, terms, abort.signal, current.period, options.stateDir);
|
|
7400
7720
|
const initial = await storage.current(journeyId);
|
|
7401
7721
|
if (!initial?.consent) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
7402
7722
|
const formed = initial.snapshotId ? [] : namedJourneyWorks(formJourneyWorks(plan.approval, options.processing.environment), options.processing, abort.signal);
|
|
@@ -10374,6 +10694,22 @@ function createJourneyOwnerClient(options) {
|
|
|
10374
10694
|
const { headers } = await requestWithHeaders("/me/profile", publicProfileSchema, signal);
|
|
10375
10695
|
return { parallelCompletes: (headers.get("passport-capabilities") ?? "").split(",").some((token) => token.trim() === "parallel-completes") };
|
|
10376
10696
|
},
|
|
10697
|
+
readProfile(signal) {
|
|
10698
|
+
return request("/me/profile", ownerProfileSchema, signal, void 0, "GET");
|
|
10699
|
+
},
|
|
10700
|
+
async saveProfile(profile, signal) {
|
|
10701
|
+
await request("/me/profile", ownerProfileSchema, signal, profile, "PUT");
|
|
10702
|
+
},
|
|
10703
|
+
async addressTaken(address, signal) {
|
|
10704
|
+
const path = `/addresses/${encodeURIComponent(passportAddressSchema.parse(address))}`;
|
|
10705
|
+
try {
|
|
10706
|
+
await request(path, z.object({ publicId: z.string() }).strict(), signal, void 0, "GET");
|
|
10707
|
+
return true;
|
|
10708
|
+
} catch (error) {
|
|
10709
|
+
if (error instanceof JourneyRemoteError && error.status === 404) return false;
|
|
10710
|
+
throw error;
|
|
10711
|
+
}
|
|
10712
|
+
},
|
|
10377
10713
|
resolve(input, signal) {
|
|
10378
10714
|
return request("/me/work-bundles/resolve", sendResolutionSchema.refine((value) => value.logicalWorkId === input.logicalWorkId), signal, input);
|
|
10379
10715
|
},
|
|
@@ -10963,7 +11299,13 @@ function resumeState(send) {
|
|
|
10963
11299
|
status: "sign-in",
|
|
10964
11300
|
error: null
|
|
10965
11301
|
};
|
|
10966
|
-
const profileRequired = ["paused", "sign-in"].includes(send.status) || send.subject === null || [
|
|
11302
|
+
const profileRequired = ["paused", "sign-in"].includes(send.status) || send.subject === null || [
|
|
11303
|
+
"ACCOUNT_PROFILE_UNAVAILABLE",
|
|
11304
|
+
"ACCOUNT_CHANGED",
|
|
11305
|
+
"PASSPORT_ADDRESS_TAKEN",
|
|
11306
|
+
"PASSPORT_ADDRESS_RESERVED",
|
|
11307
|
+
"PASSPORT_ADDRESS_LIMIT"
|
|
11308
|
+
].includes(send.error ?? "") || send.status === "blocked" && send.items.some((item) => [
|
|
10967
11309
|
"ready",
|
|
10968
11310
|
"uploading",
|
|
10969
11311
|
"assessing",
|
|
@@ -11047,7 +11389,42 @@ async function prepareProfile(dependencies, snapshot, connection, signal) {
|
|
|
11047
11389
|
assertScope(latest.journey, latest.send);
|
|
11048
11390
|
signal.throwIfAborted();
|
|
11049
11391
|
}
|
|
11050
|
-
|
|
11392
|
+
const captured = await captureProfile(connection, guard, signal, dependencies.failure);
|
|
11393
|
+
const chosen = snapshot.journey.profile;
|
|
11394
|
+
if (captured.status !== "sending" || !chosen || !profileHasChoices(chosen)) return captured;
|
|
11395
|
+
return writeProfile(connection, chosen, guard, signal, dependencies.failure, captured);
|
|
11396
|
+
}
|
|
11397
|
+
/** Passport's refusal of the chosen address, as the code that re-shows the address card. */
|
|
11398
|
+
const addressRefusals = {
|
|
11399
|
+
address_taken: "PASSPORT_ADDRESS_TAKEN",
|
|
11400
|
+
address_reserved: "PASSPORT_ADDRESS_RESERVED",
|
|
11401
|
+
address_limit_reached: "PASSPORT_ADDRESS_LIMIT"
|
|
11402
|
+
};
|
|
11403
|
+
/**
|
|
11404
|
+
* The Journey's address and links over the owner's current settings, saved before the first
|
|
11405
|
+
* Work upload (ADR 0246). A refused address blocks the Send until the person keeps another.
|
|
11406
|
+
*/
|
|
11407
|
+
async function writeProfile(connection, chosen, guard, signal, failure, captured) {
|
|
11408
|
+
try {
|
|
11409
|
+
const current = await connection.readProfile(signal);
|
|
11410
|
+
await guard();
|
|
11411
|
+
await connection.saveProfile(mergeOwnerProfile(current.profile, chosen), signal);
|
|
11412
|
+
await guard();
|
|
11413
|
+
return captured;
|
|
11414
|
+
} catch (error) {
|
|
11415
|
+
if (signal.aborted) throw error;
|
|
11416
|
+
if (error instanceof JourneyRemoteError && error.status === 409 && addressRefusals[error.code]) return {
|
|
11417
|
+
status: "blocked",
|
|
11418
|
+
error: addressRefusals[error.code] ?? null
|
|
11419
|
+
};
|
|
11420
|
+
if (error instanceof ApplicationError) throw error;
|
|
11421
|
+
const unavailable = new ApplicationError("ACCOUNT_PROFILE_UNAVAILABLE", void 0, { cause: error });
|
|
11422
|
+
failure(unavailable.code, unavailable);
|
|
11423
|
+
return {
|
|
11424
|
+
status: "blocked",
|
|
11425
|
+
error: unavailable.code
|
|
11426
|
+
};
|
|
11427
|
+
}
|
|
11051
11428
|
}
|
|
11052
11429
|
/** Shared by native Send and Manual upload; `guard` rechecks the caller's own scope. */
|
|
11053
11430
|
async function captureProfile(connection, guard, signal, failure) {
|
|
@@ -12951,6 +13328,45 @@ function createJourneySender(dependencies, phases = 3) {
|
|
|
12951
13328
|
get(address) {
|
|
12952
13329
|
return dependencies.storage.loadSend(address.journeyId, address.sendId);
|
|
12953
13330
|
},
|
|
13331
|
+
/** The owner's current address, links and account email; null while signed out. */
|
|
13332
|
+
async ownerProfile(signal) {
|
|
13333
|
+
const connection = await dependencies.auth.connect(signal);
|
|
13334
|
+
if (!connection) return null;
|
|
13335
|
+
const { profile, accountEmail } = await connection.readProfile(signal);
|
|
13336
|
+
return {
|
|
13337
|
+
address: profile.address,
|
|
13338
|
+
links: profile.links,
|
|
13339
|
+
accountEmail
|
|
13340
|
+
};
|
|
13341
|
+
},
|
|
13342
|
+
/** A best-effort availability check for the address card; Send's save decides. */
|
|
13343
|
+
async addressTaken(input, signal) {
|
|
13344
|
+
const address = passportAddressSchema.parse(input.address);
|
|
13345
|
+
const connection = await dependencies.auth.connect(signal);
|
|
13346
|
+
if (!connection) return null;
|
|
13347
|
+
return { taken: await connection.addressTaken(address, signal) };
|
|
13348
|
+
},
|
|
13349
|
+
/**
|
|
13350
|
+
* The address or links chosen on the Sent page, after the Send reached Passport (ADR 0246,
|
|
13351
|
+
* BL-230): an explicit Keep or Add saves them at once over the current settings.
|
|
13352
|
+
*/
|
|
13353
|
+
async saveSentProfile(input, signal) {
|
|
13354
|
+
const latest = requireSend(await dependencies.storage.loadSend(input.journeyId));
|
|
13355
|
+
const chosen = latest.journey.profile;
|
|
13356
|
+
if (latest.send.status !== "completed" || !chosen || !profileHasChoices(chosen)) throw new ApplicationError("INVALID_TRANSITION");
|
|
13357
|
+
const connection = await dependencies.auth.connect(signal);
|
|
13358
|
+
if (!connection) throw new ApplicationError("ACCOUNT_SIGNED_OUT");
|
|
13359
|
+
if (latest.send.subject !== connection.subject) throw new ApplicationError("IDENTITY_REJECTED");
|
|
13360
|
+
try {
|
|
13361
|
+
const current = await connection.readProfile(signal);
|
|
13362
|
+
await connection.saveProfile(mergeOwnerProfile(current.profile, chosen), signal);
|
|
13363
|
+
} catch (error) {
|
|
13364
|
+
if (signal.aborted || error instanceof ApplicationError) throw error;
|
|
13365
|
+
const code = error instanceof JourneyRemoteError && error.status === 409 ? addressRefusals[error.code] : void 0;
|
|
13366
|
+
if (code) throw new ApplicationError(code);
|
|
13367
|
+
throw new ApplicationError("ACCOUNT_PROFILE_UNAVAILABLE", void 0, { cause: error });
|
|
13368
|
+
}
|
|
13369
|
+
},
|
|
12954
13370
|
async prepare(raw, signal) {
|
|
12955
13371
|
const input = sendPrepareSchema.parse(raw);
|
|
12956
13372
|
const snapshot = await dependencies.storage.loadSend(input.journeyId);
|
|
@@ -14986,6 +15402,18 @@ async function compose(options, callbacks, bundles) {
|
|
|
14986
15402
|
})();
|
|
14987
15403
|
return {
|
|
14988
15404
|
application,
|
|
15405
|
+
remoteWorkers: createRemotePreflight({
|
|
15406
|
+
storage: journeyStorage,
|
|
15407
|
+
harnesses,
|
|
15408
|
+
execution,
|
|
15409
|
+
stateDir,
|
|
15410
|
+
home: homedir(),
|
|
15411
|
+
roots: {
|
|
15412
|
+
codexHome: options.codexHome,
|
|
15413
|
+
claudeHome: options.claudeHome
|
|
15414
|
+
},
|
|
15415
|
+
reportFailure: (error) => diagnostics.onFailure("remote-workers", error)
|
|
15416
|
+
}),
|
|
14989
15417
|
nativeInspection: {
|
|
14990
15418
|
originals: createOriginalView(journeyStorage, stateDir),
|
|
14991
15419
|
output: createOutputView(journeyStorage, processing),
|
|
@@ -15090,6 +15518,7 @@ async function invoke(runtime, command, value, signal) {
|
|
|
15090
15518
|
const app = runtime.application;
|
|
15091
15519
|
markAgentPresence(runtime.stateDir, value);
|
|
15092
15520
|
switch (command) {
|
|
15521
|
+
case "journey.remoteWorkers": return runtime.remoteWorkers(value, signal);
|
|
15093
15522
|
case "send.get": return app.journeySend?.get(sendAddress.partial({ sendId: true }).parse(value));
|
|
15094
15523
|
case "send.prepare": return app.journeySend?.prepare(sendPrepareSchema.parse(value));
|
|
15095
15524
|
case "send.start": return app.journeySend?.start(sendStartSchema.parse(value));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as createZstdFrameCheck$1 } from "./frame-
|
|
3
|
-
import "./src-
|
|
4
|
-
import { a as isRecord } from "./model-
|
|
1
|
+
import { ln as sessionSchema } from "./locate-JYtFmKu-.mjs";
|
|
2
|
+
import { t as createZstdFrameCheck$1 } from "./frame-DGun31Uc.mjs";
|
|
3
|
+
import "./src-C1SjCDx0.mjs";
|
|
4
|
+
import { a as isRecord } from "./model-CmHypB0p.mjs";
|
|
5
5
|
import { constants } from "node:fs";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { lstat, open, stat } from "node:fs/promises";
|