@xfey/tutti 0.1.60 → 0.1.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +2 -2
  2. package/dist/collaboration-state/clarification-records.d.ts +0 -9
  3. package/dist/collaboration-state/clarification-records.js +0 -57
  4. package/dist/collaboration-state/index.d.ts +6 -5
  5. package/dist/collaboration-state/index.js +5 -4
  6. package/dist/collaboration-state/messages.d.ts +4 -6
  7. package/dist/collaboration-state/messages.js +22 -29
  8. package/dist/collaboration-state/scratchpad-source-state.d.ts +4 -12
  9. package/dist/collaboration-state/scratchpad-source-state.js +24 -58
  10. package/dist/collaboration-state/scratchpad.d.ts +1 -2
  11. package/dist/collaboration-state/scratchpad.js +0 -59
  12. package/dist/collaboration-state/storage-types.d.ts +25 -5
  13. package/dist/collaboration-state/task-compile-context.d.ts +40 -0
  14. package/dist/collaboration-state/task-compile-context.js +273 -0
  15. package/dist/collaboration-state/types.d.ts +39 -9
  16. package/dist/control-plane/clarification-commands.d.ts +0 -1
  17. package/dist/control-plane/clarification-commands.js +0 -1
  18. package/dist/control-plane/index.js +16 -3
  19. package/dist/control-plane/project-context-bootstrap.d.ts +4 -4
  20. package/dist/control-plane/project-context-bootstrap.js +7 -12
  21. package/dist/control-plane/scratchpad-auto-refresh.js +12 -1
  22. package/dist/control-plane/scratchpad-refresh-start.js +77 -94
  23. package/dist/control-plane/scratchpad-refresh.js +3 -1
  24. package/dist/control-plane/scratchpad-source-messages.d.ts +15 -7
  25. package/dist/control-plane/scratchpad-source-messages.js +53 -69
  26. package/dist/control-plane/task-compile-clarification-context.d.ts +9 -0
  27. package/dist/control-plane/task-compile-clarification-context.js +70 -0
  28. package/dist/control-plane/task-compile-continuation.js +28 -56
  29. package/dist/control-plane/task-compile-output.js +50 -14
  30. package/dist/control-plane/task-compile-start.js +119 -55
  31. package/dist/control-plane/workflows/openai.d.ts +2 -1
  32. package/dist/control-plane/workflows/openai.js +13 -27
  33. package/dist/control-plane/workflows/types.d.ts +27 -17
  34. package/dist/server-shell/cli/args.d.ts +4 -0
  35. package/dist/server-shell/cli/args.js +11 -0
  36. package/dist/server-shell/cli/cli.js +35 -11
  37. package/dist/server-shell/cli/host-server-runtime.d.ts +2 -0
  38. package/dist/server-shell/cli/host-server-runtime.js +12 -5
  39. package/dist/server-shell/cli/local-control-client.d.ts +5 -1
  40. package/dist/server-shell/cli/local-control-client.js +19 -0
  41. package/dist/server-shell/desktop-integration/manager.d.ts +2 -0
  42. package/dist/server-shell/desktop-integration/manager.js +19 -31
  43. package/dist/server-shell/http/routes/local-control.d.ts +2 -0
  44. package/dist/server-shell/http/routes/local-control.js +24 -0
  45. package/dist/server-shell/local-console/invocation-context.js +10 -1
  46. package/dist/server-shell/local-console/operation-coordinator.d.ts +16 -0
  47. package/dist/server-shell/local-console/operation-coordinator.js +50 -0
  48. package/dist/server-shell/local-console/package-update-completion.d.ts +25 -0
  49. package/dist/server-shell/local-console/package-update-completion.js +91 -0
  50. package/dist/server-shell/local-console/package-update-hosts.d.ts +17 -0
  51. package/dist/server-shell/local-console/package-update-hosts.js +92 -0
  52. package/dist/server-shell/local-console/package-update-lock.d.ts +46 -0
  53. package/dist/server-shell/local-console/package-update-lock.js +223 -0
  54. package/dist/server-shell/local-console/package-update-log.d.ts +20 -0
  55. package/dist/server-shell/local-console/package-update-log.js +75 -0
  56. package/dist/server-shell/local-console/package-update-process.d.ts +22 -0
  57. package/dist/server-shell/local-console/package-update-process.js +252 -0
  58. package/dist/server-shell/local-console/package-update-record.d.ts +53 -0
  59. package/dist/server-shell/local-console/package-update-record.js +180 -0
  60. package/dist/server-shell/local-console/package-update-recovery.d.ts +34 -0
  61. package/dist/server-shell/local-console/package-update-recovery.js +140 -0
  62. package/dist/server-shell/local-console/package-update-service.d.ts +72 -0
  63. package/dist/server-shell/local-console/package-update-service.js +400 -0
  64. package/dist/server-shell/local-console/package-update-worker.d.ts +55 -0
  65. package/dist/server-shell/local-console/package-update-worker.js +297 -0
  66. package/dist/server-shell/local-console/project-service.d.ts +2 -0
  67. package/dist/server-shell/local-console/project-service.js +16 -12
  68. package/dist/server-shell/local-console/server.d.ts +9 -0
  69. package/dist/server-shell/local-console/server.js +92 -4
  70. package/dist/server-shell/package-installation/command.d.ts +36 -0
  71. package/dist/server-shell/package-installation/command.js +162 -0
  72. package/dist/server-shell/package-installation/discovery.d.ts +51 -0
  73. package/dist/server-shell/package-installation/discovery.js +137 -0
  74. package/dist/server-shell/package-installation/index.d.ts +5 -0
  75. package/dist/server-shell/package-installation/index.js +5 -0
  76. package/dist/server-shell/package-installation/installation.d.ts +34 -0
  77. package/dist/server-shell/package-installation/installation.js +123 -0
  78. package/dist/server-shell/package-installation/semver.d.ts +9 -0
  79. package/dist/server-shell/package-installation/semver.js +84 -0
  80. package/migrations/0014_scratchpad_task_compile_context.sql +147 -0
  81. package/migrations/README.md +2 -1
  82. package/package.json +1 -1
  83. package/prompts/procedures/README.md +3 -3
  84. package/prompts/procedures/scratchpad-refresh.md +17 -9
  85. package/prompts/procedures/task-compile.md +6 -3
  86. package/prompts/prompt-flow-map.md +21 -14
  87. package/web/assets/{homepage-motion-scene-CY7o4hnR.js → homepage-motion-scene-CRmrkkEH.js} +1 -1
  88. package/web/assets/{index-B08r3x8o.js → index-C9JrplHV.js} +14 -14
  89. package/web/assets/{index-DpabiRgp.css → index-IZKcmU_g.css} +1 -1
  90. package/web/index.html +2 -2
@@ -0,0 +1,180 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ID_PREFIXES, isPrefixedId } from "@tutti/shared/ids";
4
+ import { compareExactSemver, parseExactSemver } from "../package-installation/index.js";
5
+ const DEFAULT_MAX_RECORD_AGE_MS = 24 * 60 * 60 * 1_000;
6
+ const RECORD_KEYS = [
7
+ "failure_reason_code",
8
+ "phase",
9
+ "restart_failure_count",
10
+ "restore_project_ids",
11
+ "schema_version",
12
+ "source_version",
13
+ "started_at",
14
+ "target_version",
15
+ "updated_at",
16
+ "updater_pid",
17
+ ];
18
+ export function packageUpdateRuntimeRecordPath(tuttiHome) {
19
+ return join(tuttiHome, "runtime", "package-update.json");
20
+ }
21
+ function isIsoTimestamp(value) {
22
+ return typeof value === "string" && Number.isFinite(Date.parse(value));
23
+ }
24
+ function isStableReason(value) {
25
+ return typeof value === "string" && /^[a-z][a-z0-9_]{0,79}$/u.test(value);
26
+ }
27
+ function parseRecord(value) {
28
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
29
+ return null;
30
+ }
31
+ const candidate = value;
32
+ if (Object.keys(candidate).some((key) => !RECORD_KEYS.includes(key))) {
33
+ return null;
34
+ }
35
+ const source = parseExactSemver(candidate.source_version);
36
+ const target = parseExactSemver(candidate.target_version);
37
+ const phases = [
38
+ "preparing",
39
+ "stopping_hosts",
40
+ "installing",
41
+ "restarting",
42
+ "failed",
43
+ ];
44
+ if (candidate.schema_version !== 1 ||
45
+ source === null ||
46
+ target === null ||
47
+ compareExactSemver(target, source) <= 0 ||
48
+ !phases.includes(candidate.phase) ||
49
+ !Array.isArray(candidate.restore_project_ids) ||
50
+ !candidate.restore_project_ids.every((projectId) => typeof projectId === "string" && isPrefixedId(projectId, ID_PREFIXES.project)) ||
51
+ new Set(candidate.restore_project_ids).size !== candidate.restore_project_ids.length ||
52
+ !Number.isInteger(candidate.updater_pid) ||
53
+ candidate.updater_pid <= 0 ||
54
+ !isIsoTimestamp(candidate.started_at) ||
55
+ !isIsoTimestamp(candidate.updated_at) ||
56
+ Date.parse(candidate.updated_at) < Date.parse(candidate.started_at) ||
57
+ (candidate.failure_reason_code !== undefined &&
58
+ !isStableReason(candidate.failure_reason_code)) ||
59
+ (candidate.restart_failure_count !== undefined &&
60
+ (!Number.isInteger(candidate.restart_failure_count) ||
61
+ candidate.restart_failure_count < 0))) {
62
+ return null;
63
+ }
64
+ return {
65
+ schema_version: 1,
66
+ source_version: source,
67
+ target_version: target,
68
+ phase: candidate.phase,
69
+ restore_project_ids: [...candidate.restore_project_ids].sort(),
70
+ updater_pid: candidate.updater_pid,
71
+ started_at: candidate.started_at,
72
+ updated_at: candidate.updated_at,
73
+ ...(candidate.failure_reason_code === undefined
74
+ ? {}
75
+ : { failure_reason_code: candidate.failure_reason_code }),
76
+ ...(candidate.restart_failure_count === undefined
77
+ ? {}
78
+ : { restart_failure_count: candidate.restart_failure_count }),
79
+ };
80
+ }
81
+ export function readPackageUpdateRuntimeRecord(options) {
82
+ const path = packageUpdateRuntimeRecordPath(options.tuttiHome);
83
+ if (!existsSync(path)) {
84
+ return { status: "missing" };
85
+ }
86
+ try {
87
+ const record = parseRecord(JSON.parse(readFileSync(path, "utf8")));
88
+ if (record === null ||
89
+ (options.now ?? Date.now)() - Date.parse(record.updated_at) >
90
+ (options.maxAgeMs ?? DEFAULT_MAX_RECORD_AGE_MS)) {
91
+ return { status: "invalid" };
92
+ }
93
+ return { status: "valid", record };
94
+ }
95
+ catch {
96
+ return { status: "invalid" };
97
+ }
98
+ }
99
+ export function writePackageUpdateRuntimeRecord(tuttiHome, record) {
100
+ const parsed = parseRecord(record);
101
+ if (parsed === null) {
102
+ throw new Error("Package update runtime record is invalid.");
103
+ }
104
+ const path = packageUpdateRuntimeRecordPath(tuttiHome);
105
+ const directory = dirname(path);
106
+ const temporaryPath = `${path}.${process.pid}.${Date.now()}.tmp`;
107
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
108
+ chmodSync(directory, 0o700);
109
+ try {
110
+ writeFileSync(temporaryPath, `${JSON.stringify(parsed)}\n`, { encoding: "utf8", mode: 0o600 });
111
+ chmodSync(temporaryPath, 0o600);
112
+ renameSync(temporaryPath, path);
113
+ chmodSync(path, 0o600);
114
+ }
115
+ finally {
116
+ try {
117
+ unlinkSync(temporaryPath);
118
+ }
119
+ catch {
120
+ // Atomic rename normally removes the temporary path.
121
+ }
122
+ }
123
+ }
124
+ export function deletePackageUpdateRuntimeRecord(options) {
125
+ const read = readPackageUpdateRuntimeRecord({ tuttiHome: options.tuttiHome });
126
+ if (read.status === "missing") {
127
+ return true;
128
+ }
129
+ if (read.status !== "valid" ||
130
+ (options.expectedTargetVersion !== undefined &&
131
+ read.record.target_version !== options.expectedTargetVersion) ||
132
+ (options.expectedUpdaterPid !== undefined &&
133
+ read.record.updater_pid !== options.expectedUpdaterPid)) {
134
+ return false;
135
+ }
136
+ try {
137
+ unlinkSync(packageUpdateRuntimeRecordPath(options.tuttiHome));
138
+ return true;
139
+ }
140
+ catch {
141
+ return false;
142
+ }
143
+ }
144
+ export function updatePackageUpdateRuntimeRecord(options) {
145
+ const updated = {
146
+ ...options.current,
147
+ phase: options.phase,
148
+ updater_pid: options.updaterPid ?? options.current.updater_pid,
149
+ updated_at: (options.now ?? (() => new Date()))().toISOString(),
150
+ ...(options.failureReasonCode === undefined
151
+ ? {}
152
+ : { failure_reason_code: options.failureReasonCode }),
153
+ ...(options.restartFailureCount === undefined
154
+ ? {}
155
+ : { restart_failure_count: options.restartFailureCount }),
156
+ };
157
+ writePackageUpdateRuntimeRecord(options.tuttiHome, updated);
158
+ return updated;
159
+ }
160
+ export function consumePackageUpdateCompletion(options) {
161
+ const read = readPackageUpdateRuntimeRecord({ tuttiHome: options.tuttiHome });
162
+ if (read.status !== "valid" ||
163
+ read.record.phase !== "restarting" ||
164
+ read.record.target_version !== options.currentVersion ||
165
+ read.record.restart_failure_count === undefined) {
166
+ return undefined;
167
+ }
168
+ if (!deletePackageUpdateRuntimeRecord({
169
+ tuttiHome: options.tuttiHome,
170
+ expectedTargetVersion: read.record.target_version,
171
+ })) {
172
+ return undefined;
173
+ }
174
+ return {
175
+ source_version: read.record.source_version,
176
+ target_version: read.record.target_version,
177
+ restart_failure_count: read.record.restart_failure_count,
178
+ };
179
+ }
180
+ //# sourceMappingURL=package-update-record.js.map
@@ -0,0 +1,34 @@
1
+ import type { ProjectId } from "@tutti/shared/ids";
2
+ import { type PackageUpdateLockAcquisition, type PackageUpdateLockInspection } from "./package-update-lock.js";
3
+ import { type PackageUpdateRuntimeRecord, type PackageUpdateRuntimeRecordRead } from "./package-update-record.js";
4
+ export type PackageUpdateStartupRecoveryResult = {
5
+ status: "continue";
6
+ } | {
7
+ status: "completed";
8
+ url: string;
9
+ restart_failure_count: number;
10
+ };
11
+ type HostRestoreResult = {
12
+ restored_project_ids: ProjectId[];
13
+ failed_project_ids: ProjectId[];
14
+ };
15
+ export declare function recoverPackageUpdateForConsoleStartup(options: {
16
+ tuttiHome: string;
17
+ cliEntrypoint: string;
18
+ cwd: string;
19
+ env: NodeJS.ProcessEnv;
20
+ source: "terminal" | "desktop";
21
+ currentVersion?: string;
22
+ readRecord?: () => PackageUpdateRuntimeRecordRead;
23
+ inspectLock?: () => PackageUpdateLockInspection;
24
+ removeRecoverableLock?: () => boolean;
25
+ acquireLock?: () => PackageUpdateLockAcquisition;
26
+ restoreHosts?: (record: PackageUpdateRuntimeRecord) => Promise<HostRestoreResult>;
27
+ deleteRecord?: (record: PackageUpdateRuntimeRecord) => boolean;
28
+ ensureConsole?: () => Promise<{
29
+ url: string;
30
+ }>;
31
+ now?: () => Date;
32
+ }): Promise<PackageUpdateStartupRecoveryResult>;
33
+ export {};
34
+ //# sourceMappingURL=package-update-recovery.d.ts.map
@@ -0,0 +1,140 @@
1
+ import { readCliVersion } from "../cli/version.js";
2
+ import { ensureLocalConsole } from "./managed-console.js";
3
+ import { runPackageUpdateCompletion } from "./package-update-completion.js";
4
+ import { restorePackageUpdateHosts } from "./package-update-hosts.js";
5
+ import { inspectPackageUpdateLock, removeRecoverablePackageUpdateLock, tryAcquirePackageUpdateLock, } from "./package-update-lock.js";
6
+ import { PackageUpdateLogger } from "./package-update-log.js";
7
+ import { deletePackageUpdateRuntimeRecord, readPackageUpdateRuntimeRecord, updatePackageUpdateRuntimeRecord, } from "./package-update-record.js";
8
+ export async function recoverPackageUpdateForConsoleStartup(options) {
9
+ const currentVersion = options.currentVersion ?? readCliVersion();
10
+ const readRecord = options.readRecord ?? (() => readPackageUpdateRuntimeRecord({ tuttiHome: options.tuttiHome }));
11
+ const initialRecord = readRecord();
12
+ if (initialRecord.status !== "valid" || initialRecord.record.phase === "failed") {
13
+ return { status: "continue" };
14
+ }
15
+ const inspectLock = options.inspectLock ?? (() => inspectPackageUpdateLock({ tuttiHome: options.tuttiHome }));
16
+ const lockState = inspectLock();
17
+ if (lockState.status === "active") {
18
+ return { status: "continue" };
19
+ }
20
+ if (lockState.status === "recovery_required") {
21
+ const removed = (options.removeRecoverableLock ??
22
+ (() => removeRecoverablePackageUpdateLock({ tuttiHome: options.tuttiHome })))();
23
+ if (!removed) {
24
+ return { status: "continue" };
25
+ }
26
+ }
27
+ const acquisition = (options.acquireLock ?? (() => tryAcquirePackageUpdateLock({ tuttiHome: options.tuttiHome })))();
28
+ if (acquisition.status !== "acquired") {
29
+ return { status: "continue" };
30
+ }
31
+ const logger = new PackageUpdateLogger({
32
+ tuttiHome: options.tuttiHome,
33
+ privatePaths: [options.tuttiHome],
34
+ ...(options.now === undefined ? {} : { now: options.now }),
35
+ });
36
+ const log = (entry) => {
37
+ try {
38
+ logger.append(entry);
39
+ }
40
+ catch {
41
+ // Recovery correctness must not depend on the diagnostic log.
42
+ }
43
+ };
44
+ let lockReleased = false;
45
+ const releaseLock = () => {
46
+ if (!lockReleased) {
47
+ lockReleased = true;
48
+ acquisition.lease.release();
49
+ }
50
+ return true;
51
+ };
52
+ const current = readRecord();
53
+ if (current.status !== "valid" || current.record.phase === "failed") {
54
+ releaseLock();
55
+ return { status: "continue" };
56
+ }
57
+ const record = current.record;
58
+ const restoreHosts = options.restoreHosts ??
59
+ ((value) => restorePackageUpdateHosts({
60
+ tuttiHome: options.tuttiHome,
61
+ projectIds: value.restore_project_ids,
62
+ env: options.env,
63
+ }));
64
+ if (record.source_version === currentVersion) {
65
+ let restored;
66
+ try {
67
+ restored = await restoreHosts(record);
68
+ }
69
+ catch {
70
+ restored = {
71
+ restored_project_ids: [],
72
+ failed_project_ids: [...record.restore_project_ids],
73
+ };
74
+ }
75
+ const deleted = (options.deleteRecord ??
76
+ ((value) => deletePackageUpdateRuntimeRecord({
77
+ tuttiHome: options.tuttiHome,
78
+ expectedTargetVersion: value.target_version,
79
+ expectedUpdaterPid: value.updater_pid,
80
+ })))(record);
81
+ releaseLock();
82
+ const recoveryIncomplete = restored.failed_project_ids.length > 0 || !deleted;
83
+ log({
84
+ level: restored.failed_project_ids.length === 0 && deleted ? "info" : "warn",
85
+ message: restored.failed_project_ids.length === 0 && deleted
86
+ ? "Recovered an interrupted package update using the source CLI."
87
+ : "Package update source recovery requires follow-up.",
88
+ ...(recoveryIncomplete ? { reasonCode: "update_recovery_required" } : {}),
89
+ });
90
+ return { status: "continue" };
91
+ }
92
+ if (record.target_version !== currentVersion) {
93
+ releaseLock();
94
+ return { status: "continue" };
95
+ }
96
+ const completionRecord = updatePackageUpdateRuntimeRecord({
97
+ tuttiHome: options.tuttiHome,
98
+ current: record,
99
+ phase: "restarting",
100
+ updaterPid: process.pid,
101
+ ...(options.now === undefined ? {} : { now: options.now }),
102
+ });
103
+ let consoleUrl;
104
+ try {
105
+ const completion = await runPackageUpdateCompletion({
106
+ tuttiHome: options.tuttiHome,
107
+ cliEntrypoint: options.cliEntrypoint,
108
+ env: options.env,
109
+ currentVersion,
110
+ logger,
111
+ restoreHosts: async () => await restoreHosts(completionRecord),
112
+ ensureConsole: async () => {
113
+ const result = await (options.ensureConsole ??
114
+ (() => ensureLocalConsole({
115
+ cwd: options.cwd,
116
+ env: options.env,
117
+ source: options.source,
118
+ })))();
119
+ consoleUrl = result.url;
120
+ return result;
121
+ },
122
+ openBrowser: () => false,
123
+ releaseLock,
124
+ ...(options.now === undefined ? {} : { now: options.now }),
125
+ });
126
+ if (consoleUrl === undefined) {
127
+ throw new Error("Recovered package update did not start a Local Console.");
128
+ }
129
+ return {
130
+ status: "completed",
131
+ url: consoleUrl,
132
+ restart_failure_count: completion.restart_failure_count,
133
+ };
134
+ }
135
+ catch {
136
+ releaseLock();
137
+ return { status: "continue" };
138
+ }
139
+ }
140
+ //# sourceMappingURL=package-update-recovery.js.map
@@ -0,0 +1,72 @@
1
+ import type { ProjectId } from "@tutti/shared/ids";
2
+ import { type MachineProjectInspection } from "../cli/machine-project-inspector.js";
3
+ import { type GlobalPackageInstallation, type GlobalPackageInstallationResolution, type PackageInstallationUnavailableReason, type PackageUpdateDiscovery, type PublishedPackageTarget } from "../package-installation/index.js";
4
+ import { LocalConsoleOperationCoordinator } from "./operation-coordinator.js";
5
+ import { type PackageUpdateLockAcquisition, type PackageUpdateLockInspection } from "./package-update-lock.js";
6
+ import { type PackageUpdateRuntimeRecordRead } from "./package-update-record.js";
7
+ export type LocalConsolePackageUpdateReason = PackageInstallationUnavailableReason | "registry_unavailable" | "console_busy" | "host_busy" | "host_identity_unverified" | "host_update_unsupported" | "update_in_progress" | "update_recovery_required" | "npm_install_failed" | "post_install_validation_failed" | "completion_start_failed" | "completion_failed" | "worker_crashed" | "host_restore_failed";
8
+ export type LocalConsolePackageUpdateStatus = {
9
+ current_version: string;
10
+ latest_version?: string;
11
+ status: "up_to_date" | "ready" | "blocked" | "updating" | "failed";
12
+ can_update: boolean;
13
+ reason_code?: LocalConsolePackageUpdateReason;
14
+ phase?: "preparing" | "stopping_hosts" | "installing" | "restarting";
15
+ };
16
+ export type PackageUpdateHostReadiness = {
17
+ status: "ready";
18
+ restore_project_ids: ProjectId[];
19
+ } | {
20
+ status: "blocked";
21
+ reason_code: "host_busy" | "host_identity_unverified" | "host_update_unsupported";
22
+ };
23
+ export type PackageUpdatePreparationLease = {
24
+ handoffTo: (pid: number) => void;
25
+ release: () => void;
26
+ cancel: () => void;
27
+ };
28
+ export type LocalConsolePackageUpdatePreparation = {
29
+ installation: GlobalPackageInstallation;
30
+ target: PublishedPackageTarget;
31
+ restore_project_ids: ProjectId[];
32
+ lease: PackageUpdatePreparationLease;
33
+ };
34
+ export type BeginLocalConsolePackageUpdateResult = {
35
+ status: "ready";
36
+ preparation: LocalConsolePackageUpdatePreparation;
37
+ } | {
38
+ status: "blocked";
39
+ update: LocalConsolePackageUpdateStatus;
40
+ };
41
+ type HostReadinessReader = (inspection: MachineProjectInspection) => Promise<"ready" | "busy" | "unsupported">;
42
+ export declare function inspectPackageUpdateHosts(options: {
43
+ projects: readonly MachineProjectInspection[];
44
+ readReadiness: HostReadinessReader;
45
+ }): Promise<PackageUpdateHostReadiness>;
46
+ export declare class LocalConsolePackageUpdateService {
47
+ #private;
48
+ constructor(options: {
49
+ tuttiHome: string;
50
+ env?: NodeJS.ProcessEnv;
51
+ currentVersion?: string;
52
+ operations?: LocalConsoleOperationCoordinator;
53
+ resolveInstallation?: () => GlobalPackageInstallationResolution;
54
+ discover?: (resolution: GlobalPackageInstallationResolution, options: {
55
+ refresh?: boolean;
56
+ }) => Promise<PackageUpdateDiscovery>;
57
+ inspectProjects?: () => Promise<MachineProjectInspection[]>;
58
+ readReadiness?: HostReadinessReader;
59
+ inspectLock?: () => PackageUpdateLockInspection;
60
+ acquireLock?: () => PackageUpdateLockAcquisition;
61
+ readRecord?: () => PackageUpdateRuntimeRecordRead;
62
+ clearFailedRecord?: (record: Extract<PackageUpdateRuntimeRecordRead, {
63
+ status: "valid";
64
+ }>["record"]) => boolean;
65
+ });
66
+ getStatus(options?: {
67
+ refresh?: boolean;
68
+ }): Promise<LocalConsolePackageUpdateStatus>;
69
+ beginUpdate(): Promise<BeginLocalConsolePackageUpdateResult>;
70
+ }
71
+ export {};
72
+ //# sourceMappingURL=package-update-service.d.ts.map