@moondeck/station 0.0.1 → 1.0.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/LICENSE +21 -0
- package/README.md +149 -2
- package/bin/uai-host.mjs +130 -0
- package/db/migrations/0000_host_tasks.sql +12 -0
- package/db/migrations/0001_host_ui.sql +11 -0
- package/db/migrations/0002_host_github_tokens.sql +8 -0
- package/db/migrations/0003_host_ssh_keys.sql +8 -0
- package/db/migrations/0004_host_owner_name.sql +1 -0
- package/db/migrations/0005_host_env_vars.sql +5 -0
- package/db/migrations/0006_host_project_env.sql +9 -0
- package/db/migrations/0007_host_github_token_kind.sql +7 -0
- package/db/migrations/0008_host_mcp_connections.sql +18 -0
- package/db/migrations/0009_host_agent_sessions.sql +15 -0
- package/db/migrations/0010_host_engine_accounts.sql +13 -0
- package/db/migrations/0011_codex_thread_id.sql +5 -0
- package/db/migrations/0012_agent_session_attach_key.sql +4 -0
- package/db/migrations/0013_github_credential_generations.sql +11 -0
- package/db/migrations/0014_host_inventory_event_index.sql +1 -0
- package/db/migrations/0015_host_settings.sql +9 -0
- package/db/migrations/0016_task_environment.sql +2 -0
- package/db/migrations/0017_engine_account_scope.sql +7 -0
- package/db/migrations/0018_engine_account_position.sql +3 -0
- package/db/migrations/0019_engine_account_store_ref.sql +3 -0
- package/db/migrations/0020_user_credential_store_ref.sql +6 -0
- package/db/migrations/0021_project_env_store_ref.sql +3 -0
- package/db/migrations/0022_task_project_ids.sql +5 -0
- package/db/migrations/0023_project_env_org.sql +4 -0
- package/db/migrations/0024_task_env_mode.sql +9 -0
- package/db/migrations/0025_project_env_authority.sql +147 -0
- package/db/migrations/0026_project_env_replica.sql +150 -0
- package/db/migrations/0027_cloud_credential_foundation.sql +51 -0
- package/db/migrations/0028_leased_engine_runtimes.sql +11 -0
- package/db/migrations/0029_task_shared_files_mode.sql +5 -0
- package/db/migrations/0030_credential_cleanup_restops.sql +12 -0
- package/db/migrations/meta/_journal.json +223 -0
- package/db/schema.ts +850 -0
- package/images/standard/Dockerfile +347 -0
- package/images/standard/README.md +167 -0
- package/images/standard/container/code-server-settings.json +63 -0
- package/images/standard/container/corepack-version +1 -0
- package/images/standard/container/uai-init +704 -0
- package/images/standard/container/uai-materialize-runtimes +1527 -0
- package/images/standard/container/uai-task-forwarder.mjs +303 -0
- package/images/standard/tool-versions +2 -0
- package/lib/__fixtures__/skill-index/SKILL.md +10 -0
- package/lib/__fixtures__/skill-index/skills/accessibility-checklist.md +7 -0
- package/lib/__fixtures__/skill-index/skills/brand-voice.md +9 -0
- package/lib/__fixtures__/skill-index/skills/design-tokens.md +9 -0
- package/lib/agent-cli.ts +1507 -0
- package/lib/agent-errors.ts +22 -0
- package/lib/agent.ts +672 -0
- package/lib/agents/attach-compatibility.ts +51 -0
- package/lib/agents/claude.ts +918 -0
- package/lib/agents/codex-token-usage.fixture.json +130 -0
- package/lib/agents/codex.ts +1392 -0
- package/lib/agents/cursor-period-usage.ts +253 -0
- package/lib/agents/cursor.ts +562 -0
- package/lib/agents/dispatch.ts +78 -0
- package/lib/agents/durable-proc.ts +334 -0
- package/lib/agents/factory.ts +57 -0
- package/lib/agents/grok.ts +381 -0
- package/lib/agents/kimi.ts +329 -0
- package/lib/agents/machine-durable.ts +604 -0
- package/lib/agents/mock.ts +133 -0
- package/lib/agents/mode.ts +64 -0
- package/lib/agents/opencode.ts +508 -0
- package/lib/agents/output-source.ts +3 -0
- package/lib/agents/proc.ts +221 -0
- package/lib/agents/rate-limit.ts +337 -0
- package/lib/agents/registry.ts +182 -0
- package/lib/agents/session-state.ts +197 -0
- package/lib/agents/skill-index-preamble.fixture.ts +26 -0
- package/lib/agents/transport.ts +741 -0
- package/lib/agents/types.ts +254 -0
- package/lib/agents/uai.ts +106 -0
- package/lib/agents/usage.ts +44 -0
- package/lib/apple-one-off.ts +277 -0
- package/lib/apple-runtime-recycle.ts +237 -0
- package/lib/apple-uninstall-teardown.ts +224 -0
- package/lib/assignment-evidence.ts +94 -0
- package/lib/attachments.ts +48 -0
- package/lib/browser-testing.ts +1537 -0
- package/lib/capture-flow.ts +332 -0
- package/lib/cloud-credential-cleanup-adapter.ts +123 -0
- package/lib/cloud-credential-host.ts +512 -0
- package/lib/cloud-credential-leases.ts +2587 -0
- package/lib/cloud-credential-runtime.ts +1357 -0
- package/lib/cloud-state.ts +56 -0
- package/lib/codex-auth.ts +456 -0
- package/lib/command-db.ts +310 -0
- package/lib/compose-network-recovery.ts +283 -0
- package/lib/connection-secret-redaction.ts +25 -0
- package/lib/container-runtime.ts +1453 -0
- package/lib/credential-cleanup-inventory.ts +490 -0
- package/lib/credential-consumers/engine-anchor.ts +1880 -0
- package/lib/credential-consumers/engines.ts +797 -0
- package/lib/credential-consumers/files.ts +934 -0
- package/lib/credential-consumers/github.ts +702 -0
- package/lib/credential-consumers/mcp.ts +389 -0
- package/lib/credential-consumers/task-files.ts +127 -0
- package/lib/credential-consumers/task-secrets.ts +10 -0
- package/lib/credential-store-pickup.ts +149 -0
- package/lib/credential-store-scope.ts +112 -0
- package/lib/credential-store.ts +932 -0
- package/lib/credentials-activation-authority.ts +709 -0
- package/lib/credentials-purge.ts +1006 -0
- package/lib/custom-connection-capture.ts +395 -0
- package/lib/custom-connection-launch.ts +384 -0
- package/lib/custom-connection-runtime.ts +141 -0
- package/lib/db.ts +80 -0
- package/lib/disk-pressure.ts +42 -0
- package/lib/docker-exec.ts +156 -0
- package/lib/engine-accounts.ts +1970 -0
- package/lib/engine-connect.ts +321 -0
- package/lib/engine-credential-env.ts +52 -0
- package/lib/engine-login.ts +2933 -0
- package/lib/engines.ts +1342 -0
- package/lib/enrollment-state.ts +251 -0
- package/lib/env-file.ts +246 -0
- package/lib/env-schema.ts +891 -0
- package/lib/env.ts +195 -0
- package/lib/fs-aliases.ts +49 -0
- package/lib/git-clone-credentials.ts +334 -0
- package/lib/git-diff.ts +530 -0
- package/lib/git-identity.ts +715 -0
- package/lib/github-git-auth.ts +207 -0
- package/lib/github-origin.ts +28 -0
- package/lib/github-tokens.ts +2439 -0
- package/lib/host-cloud-url.ts +62 -0
- package/lib/host-config.ts +279 -0
- package/lib/host-env.ts +424 -0
- package/lib/host-logs.ts +965 -0
- package/lib/internal-connections.ts +5 -0
- package/lib/keyed-promise-tail.ts +23 -0
- package/lib/launch-mode.ts +25 -0
- package/lib/lease.ts +239 -0
- package/lib/legacy-host.ts +769 -0
- package/lib/legacy-runtime-retirement.ts +424 -0
- package/lib/legacy-runtime-v1.fixture.ts +627 -0
- package/lib/machine-exec.ts +238 -0
- package/lib/machine-gateway-tunnel.ts +344 -0
- package/lib/machine-keys.ts +65 -0
- package/lib/machine-project-env-loader.ts +152 -0
- package/lib/machine-provider-aws.ts +923 -0
- package/lib/machine-provider-local.ts +338 -0
- package/lib/machine-provider.ts +90 -0
- package/lib/managed-activation-watcher.ts +72 -0
- package/lib/managed-install-owner-watcher.ts +55 -0
- package/lib/managed-operation-drain.ts +57 -0
- package/lib/managed-runtime.ts +4296 -0
- package/lib/managed-update-scheduler.ts +125 -0
- package/lib/mcp-capture.ts +865 -0
- package/lib/mcp-config-lock.ts +2 -0
- package/lib/mcp-connections.ts +959 -0
- package/lib/mcp-gateway.ts +2594 -0
- package/lib/obs.ts +512 -0
- package/lib/openrouter-budget.ts +247 -0
- package/lib/orchestrator.ts +11409 -0
- package/lib/person-capture.ts +327 -0
- package/lib/preview-ports.ts +85 -0
- package/lib/preview-sidecar.ts +331 -0
- package/lib/project-env-authority.ts +1319 -0
- package/lib/project-env-feature.ts +74 -0
- package/lib/project-env-legacy-tags.ts +130 -0
- package/lib/project-env-loader.ts +242 -0
- package/lib/project-env-replica.ts +2094 -0
- package/lib/project-env-schema-capture.ts +342 -0
- package/lib/project-env-staging.ts +148 -0
- package/lib/project-env-task-policy.ts +176 -0
- package/lib/project-env-task-replica.ts +1752 -0
- package/lib/release-feed.ts +61 -0
- package/lib/release-manifest.ts +710 -0
- package/lib/release-trust.ts +46 -0
- package/lib/repo-clone.ts +38 -0
- package/lib/routing/shadow.ts +261 -0
- package/lib/runner-boot.ts +10 -0
- package/lib/runtime-activation-tail.ts +279 -0
- package/lib/runtime-archive.ts +1216 -0
- package/lib/runtime-authority.ts +166 -0
- package/lib/runtime-guard.ts +36 -0
- package/lib/runtime-provider-state.ts +169 -0
- package/lib/runtime-reconnect.ts +86 -0
- package/lib/runtime-state.ts +1033 -0
- package/lib/safe-http.ts +364 -0
- package/lib/secrets-proxy/address.ts +95 -0
- package/lib/secrets-proxy/audit.ts +30 -0
- package/lib/secrets-proxy/ca-store.ts +200 -0
- package/lib/secrets-proxy/ca.ts +470 -0
- package/lib/secrets-proxy/container-steps.ts +138 -0
- package/lib/secrets-proxy/der.ts +273 -0
- package/lib/secrets-proxy/engine.ts +1633 -0
- package/lib/secrets-proxy/host.ts +93 -0
- package/lib/secrets-proxy/hostname.ts +57 -0
- package/lib/secrets-proxy/placeholders.ts +196 -0
- package/lib/secrets-proxy/policy.ts +150 -0
- package/lib/secrets-proxy/readiness.ts +148 -0
- package/lib/secrets-proxy/runtime.ts +582 -0
- package/lib/secrets-proxy/scrub.ts +559 -0
- package/lib/secrets-proxy/sidecar-view.ts +139 -0
- package/lib/secrets-proxy/task-scripts.ts +262 -0
- package/lib/secrets-proxy/task-trust.ts +605 -0
- package/lib/secrets-proxy/trust-watch.ts +80 -0
- package/lib/secrets.ts +71 -0
- package/lib/shared-files-s3.ts +976 -0
- package/lib/shared-files.ts +156 -0
- package/lib/sidecar-assign.ts +49 -0
- package/lib/sidecar-guard.ts +58 -0
- package/lib/sidecar-resume.ts +178 -0
- package/lib/sidecar.ts +69 -0
- package/lib/signin-box-credentials.ts +465 -0
- package/lib/signin-box.ts +114 -0
- package/lib/skill-index-example.fixture.ts +56 -0
- package/lib/skill-layout.ts +417 -0
- package/lib/skills.ts +489 -0
- package/lib/ssh.ts +401 -0
- package/lib/standard-image-cleanup.ts +117 -0
- package/lib/standard-image-pin.ts +207 -0
- package/lib/standard-image.ts +1697 -0
- package/lib/stopped-task-status-queue.ts +120 -0
- package/lib/task-container-cli.ts +269 -0
- package/lib/task-credential-cleanup.ts +752 -0
- package/lib/task-diff-sandbox.ts +464 -0
- package/lib/task-diff.ts +91 -0
- package/lib/task-env-forwarder.ts +228 -0
- package/lib/task-env-source.ts +249 -0
- package/lib/task-environment/anchor.ts +31 -0
- package/lib/task-environment/apple-container.ts +860 -0
- package/lib/task-environment/docker.ts +1344 -0
- package/lib/task-environment/index.ts +466 -0
- package/lib/task-environment/legacy-adoption.ts +467 -0
- package/lib/task-environment/machine-environment.ts +61 -0
- package/lib/task-environment/machine-task-up.ts +1227 -0
- package/lib/task-environment/machine.ts +974 -0
- package/lib/task-environment/registry.ts +59 -0
- package/lib/task-environment/self-identity.ts +20 -0
- package/lib/task-environment/self.ts +566 -0
- package/lib/task-environment/types.ts +642 -0
- package/lib/task-environment/workspace-files.ts +685 -0
- package/lib/task-environment/workspace-runtime.fixture.ts +50 -0
- package/lib/task-files-machine-retirement-outbox.ts +592 -0
- package/lib/task-files-machine-retirement.ts +116 -0
- package/lib/task-files-readiness.ts +127 -0
- package/lib/task-gateway-port.ts +22 -0
- package/lib/task-gateway-protocol.ts +190 -0
- package/lib/task-gateway-recovery.ts +47 -0
- package/lib/task-gateway-state.ts +512 -0
- package/lib/task-identity.ts +19 -0
- package/lib/task-inventory.ts +682 -0
- package/lib/task-machine-credentials-activation.ts +95 -0
- package/lib/task-machine-swap-safety.ts +729 -0
- package/lib/task-person-credentials.ts +76 -0
- package/lib/task-project-ops-host.ts +147 -0
- package/lib/task-project-ops.ts +1062 -0
- package/lib/task-secret-staging.ts +16 -0
- package/lib/task-status.ts +46 -0
- package/lib/task-token.ts +46 -0
- package/lib/token-broker-adopt.ts +344 -0
- package/lib/token-broker-lambda.ts +105 -0
- package/lib/token-broker-local.ts +392 -0
- package/lib/token-broker-revision.ts +310 -0
- package/lib/token-broker-ssm.ts +525 -0
- package/lib/token-broker.ts +218 -0
- package/lib/token-lanes/openai-oauth.ts +123 -0
- package/lib/token-lanes/registry.ts +45 -0
- package/lib/token-lanes/types.ts +163 -0
- package/lib/token-lanes/xai-oauth.ts +165 -0
- package/lib/transcript.ts +128 -0
- package/lib/tunnel-registry.ts +220 -0
- package/lib/tunnel-runtime.ts +235 -0
- package/lib/ulid.ts +16 -0
- package/lib/user-bus-env.ts +116 -0
- package/lib/user-credentials-store.ts +435 -0
- package/lib/vnode-pressure.ts +142 -0
- package/package.json +115 -8
- package/runner/runner.mjs +442 -0
- package/scripts/agent/_common.sh +633 -0
- package/scripts/agent/env-hook.sh +626 -0
- package/scripts/agent/moondeck-cli.sh +5 -0
- package/scripts/agent/task-down.sh +291 -0
- package/scripts/agent/task-status.sh +70 -0
- package/scripts/agent/task-up.sh +3761 -0
- package/scripts/agent/uai-env-exec.sh +26 -0
- package/scripts/install/darwin.ts +1048 -0
- package/scripts/install/linux.ts +958 -0
- package/scripts/install/types.ts +78 -0
- package/scripts/install/util.ts +254 -0
- package/scripts/install/win.ts +143 -0
- package/src/activation-respawn.ts +155 -0
- package/src/apple-tunnel-route.ts +104 -0
- package/src/capture-wire.ts +102 -0
- package/src/cli.ts +2583 -0
- package/src/cloud-credentials.ts +2144 -0
- package/src/cloud-origins.ts +23 -0
- package/src/credential-location.ts +248 -0
- package/src/credential-wire-validation.ts +25 -0
- package/src/custom-connections.ts +237 -0
- package/src/engine-account-paths.ts +11 -0
- package/src/engine-models.ts +39 -0
- package/src/engine-usage.ts +104 -0
- package/src/event-outbox.ts +185 -0
- package/src/index.ts +2899 -0
- package/src/load-env.ts +97 -0
- package/src/machine-tunnel-route.ts +156 -0
- package/src/main.ts +6349 -0
- package/src/never-proxied-domains.ts +31 -0
- package/src/outbound-frame.ts +31 -0
- package/src/paths.ts +81 -0
- package/src/project-env-latest.ts +130 -0
- package/src/project-env-policy.ts +396 -0
- package/src/project-env-wording.ts +53 -0
- package/src/protocol.ts +5545 -0
- package/src/runtime-bootstrap.ts +165 -0
- package/src/station-identity.ts +96 -0
- package/src/task-env-names.ts +28 -0
- package/src/task-secrets.ts +75 -0
- package/src/tunnel-dial.ts +102 -0
- package/src/ui/server.ts +852 -0
- package/src/ui/types.ts +173 -0
- package/src/workspace-path-policy.ts +41 -0
- package/ui/app.js +1102 -0
- package/ui/index.html +90 -0
- package/ui/style.css +685 -0
- package/ui/uai-favicon.svg +21 -0
- package/ui/uai-logo-black.svg +9 -0
- package/ui/uai-wheel.svg +9 -0
- package/bin/moondeck-station.mjs +0 -3
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restore GitHub/SSH files when a running task's cloud credentials become
|
|
3
|
+
* usable, after recovery or a live change. The persisted provider locator
|
|
4
|
+
* is the only runtime authority; a missing runtime is a retryable failure.
|
|
5
|
+
* Fresh task-up uses the same writer on its newly provisioned handle.
|
|
6
|
+
*/
|
|
7
|
+
import type { HostTask } from "../db/schema";
|
|
8
|
+
import { CredentialLeaseUnavailableError, type TaskAssignment } from "./cloud-credential-leases";
|
|
9
|
+
import { writeTaskPersonCredentials, type PersonCredentialLane } from "./credential-consumers/github";
|
|
10
|
+
import type { TaskWriteEnvironment } from "./credential-consumers/task-files";
|
|
11
|
+
import { getHostTask, readTaskRunEpochState } from "./runtime-state";
|
|
12
|
+
import { reconstructPersistedTaskEnvironment } from "./task-environment";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The composer retries a rejection while the same material is current and
|
|
16
|
+
* aborts this signal before cleanup or takeover. In particular, a fresh
|
|
17
|
+
* task that is still starting must retry: a rotation after its runtime-ready
|
|
18
|
+
* writes but before it is marked running must not be silently missed.
|
|
19
|
+
*/
|
|
20
|
+
export async function reconcileRunningTaskPersonCredentials(
|
|
21
|
+
assignment: Readonly<TaskAssignment>,
|
|
22
|
+
lanes: readonly PersonCredentialLane[],
|
|
23
|
+
signal: AbortSignal,
|
|
24
|
+
): Promise<void> {
|
|
25
|
+
const current = (): HostTask => {
|
|
26
|
+
signal.throwIfAborted();
|
|
27
|
+
const task = getHostTask(assignment.taskId);
|
|
28
|
+
const run = readTaskRunEpochState(assignment.taskId);
|
|
29
|
+
if (
|
|
30
|
+
task === null ||
|
|
31
|
+
task.statusMirror !== "running" ||
|
|
32
|
+
task.runEpoch !== assignment.runEpoch ||
|
|
33
|
+
run === null ||
|
|
34
|
+
!run.assignmentOpen ||
|
|
35
|
+
run.highestRunEpoch !== assignment.runEpoch ||
|
|
36
|
+
run.runtimeEstablishedEpoch !== assignment.runEpoch
|
|
37
|
+
) {
|
|
38
|
+
throw new CredentialLeaseUnavailableError("the task's running credential assignment is not current");
|
|
39
|
+
}
|
|
40
|
+
return task;
|
|
41
|
+
};
|
|
42
|
+
const task = current();
|
|
43
|
+
const assertCurrent = (): void => {
|
|
44
|
+
const live = current();
|
|
45
|
+
if (
|
|
46
|
+
live.environmentProvider !== task.environmentProvider ||
|
|
47
|
+
live.environmentLocator !== task.environmentLocator ||
|
|
48
|
+
live.envMode !== task.envMode
|
|
49
|
+
) {
|
|
50
|
+
throw new CredentialLeaseUnavailableError("the task's credential runtime has changed");
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const environment = await reconstructPersistedTaskEnvironment(task);
|
|
54
|
+
assertCurrent();
|
|
55
|
+
if (environment === null) {
|
|
56
|
+
throw new CredentialLeaseUnavailableError("the task's credential runtime is unavailable");
|
|
57
|
+
}
|
|
58
|
+
// Keep the exact running assignment and cancellation at each provider's
|
|
59
|
+
// last exec boundary too: reconstruction or address lookup can suspend
|
|
60
|
+
// while Stop or a new run replaces the runtime.
|
|
61
|
+
const writable: TaskWriteEnvironment = {
|
|
62
|
+
descriptor: environment.descriptor,
|
|
63
|
+
exec: (request) => {
|
|
64
|
+
assertCurrent();
|
|
65
|
+
return environment.exec({
|
|
66
|
+
...request,
|
|
67
|
+
admit: () => {
|
|
68
|
+
assertCurrent();
|
|
69
|
+
request.admit?.();
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
await writeTaskPersonCredentials(writable, assignment, lanes, signal);
|
|
75
|
+
assertCurrent();
|
|
76
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-161 §2: the live-project commands wired to this runner's real state —
|
|
3
|
+
* the task's persisted environment, its run-epoch admission, its lifecycle
|
|
4
|
+
* slot, its lease grant and env replica, and its persisted env spec.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { activeCloudCredentials, credentialsMode } from "./cloud-credential-host";
|
|
8
|
+
import { getOrchestrator } from "./orchestrator";
|
|
9
|
+
import {
|
|
10
|
+
getHostTask,
|
|
11
|
+
hostTaskProjectEnvSpec,
|
|
12
|
+
readTaskRunEpochState,
|
|
13
|
+
taskProjectEnvSpec,
|
|
14
|
+
upsertHostTask,
|
|
15
|
+
type TaskProjectEnvSpec,
|
|
16
|
+
} from "./runtime-state";
|
|
17
|
+
import { taskUaiDir } from "./env";
|
|
18
|
+
import { captureTaskEnvSchemaFromClone, taskEnvSchemaObservation } from "./project-env-schema-capture";
|
|
19
|
+
import { reconstructPersistedTaskEnvironment } from "./task-environment";
|
|
20
|
+
import { forgetTaskEnvSnapshot, taskEnvResolver } from "./task-env-source";
|
|
21
|
+
import { currentTaskGatewayRegistration, setTaskGatewayEnvResolver } from "./task-gateway-state";
|
|
22
|
+
import { TaskProjectJournalStore, TaskProjectOps } from "./task-project-ops";
|
|
23
|
+
import type { TaskCommandProject } from "../src/protocol";
|
|
24
|
+
|
|
25
|
+
function runIsCurrent(taskId: string, runEpoch: number): boolean {
|
|
26
|
+
const task = getHostTask(taskId);
|
|
27
|
+
if (!task || task.statusMirror !== "running") return false;
|
|
28
|
+
const state = readTaskRunEpochState(taskId);
|
|
29
|
+
// A task started before run epochs carries none; the cloud never sends
|
|
30
|
+
// these commands to it (it has no `live-task-projects-v1` contract).
|
|
31
|
+
return state !== null && state.assignmentOpen && state.highestRunEpoch === runEpoch;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Names the cloud's literal channel must never set live: the editor theme
|
|
35
|
+
* is the task's, chosen at start. */
|
|
36
|
+
const RESERVED_LITERAL_ENV = new Set(["UAI_EDITOR_THEME"]);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* One project (and its preview URL literals) added to a persisted env spec.
|
|
40
|
+
* Every other entry stays; a literal name the task already has keeps its
|
|
41
|
+
* value, as at start where the first project to declare one wins.
|
|
42
|
+
*/
|
|
43
|
+
export function specWithProject(
|
|
44
|
+
spec: TaskProjectEnvSpec,
|
|
45
|
+
project: TaskCommandProject,
|
|
46
|
+
previewEnv: Record<string, string> = {},
|
|
47
|
+
): TaskProjectEnvSpec {
|
|
48
|
+
const hasProject = spec.projects.some((entry) => entry.projectId === project.id);
|
|
49
|
+
const addedLiterals = Object.entries(previewEnv).filter(
|
|
50
|
+
([name]) => !RESERVED_LITERAL_ENV.has(name) && !(name in spec.previewEnv),
|
|
51
|
+
);
|
|
52
|
+
if (hasProject && addedLiterals.length === 0) return spec;
|
|
53
|
+
const [entry] = taskProjectEnvSpec({
|
|
54
|
+
projects: [project],
|
|
55
|
+
task: { previewEnv: {} } as Parameters<typeof taskProjectEnvSpec>[0]["task"],
|
|
56
|
+
}).projects;
|
|
57
|
+
return {
|
|
58
|
+
...spec,
|
|
59
|
+
projects: hasProject
|
|
60
|
+
? spec.projects
|
|
61
|
+
: [...spec.projects, entry!].sort(
|
|
62
|
+
(left, right) => left.position - right.position || left.projectId.localeCompare(right.projectId),
|
|
63
|
+
),
|
|
64
|
+
previewEnv: Object.fromEntries(
|
|
65
|
+
[...Object.entries(spec.previewEnv), ...addedLiterals].sort(([left], [right]) => left.localeCompare(right)),
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function liveProjectsSupported(taskId: string): boolean {
|
|
71
|
+
const task = getHostTask(taskId);
|
|
72
|
+
if (!task) return false;
|
|
73
|
+
try {
|
|
74
|
+
return hostTaskProjectEnvSpec(task) !== null && currentTaskGatewayRegistration(taskId) !== null;
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Persist the extended spec, then ALWAYS re-point the live resolver at the
|
|
82
|
+
* persisted spec, so a repeat repairs a resolver a crash left behind. Throws
|
|
83
|
+
* when the environment can't take it; Activate then answers `incomplete`.
|
|
84
|
+
*/
|
|
85
|
+
function installProjectEnv(
|
|
86
|
+
taskId: string,
|
|
87
|
+
runEpoch: number,
|
|
88
|
+
project: TaskCommandProject,
|
|
89
|
+
previewEnv: Record<string, string>,
|
|
90
|
+
): void {
|
|
91
|
+
const task = getHostTask(taskId);
|
|
92
|
+
if (!task) throw new Error(`no such task: ${taskId}`);
|
|
93
|
+
const spec = hostTaskProjectEnvSpec(task);
|
|
94
|
+
if (spec === null) throw new Error("this task has no persisted env spec to extend");
|
|
95
|
+
const registration = currentTaskGatewayRegistration(taskId);
|
|
96
|
+
if (!registration) throw new Error("this task has no live env gateway");
|
|
97
|
+
const next = specWithProject(spec, project, previewEnv);
|
|
98
|
+
if (next !== spec) upsertHostTask(taskId, { projectEnvSpec: JSON.stringify(next) });
|
|
99
|
+
forgetTaskEnvSnapshot(taskId);
|
|
100
|
+
if (!setTaskGatewayEnvResolver(taskId, registration.generation, taskEnvResolver(taskId, next, runEpoch))) {
|
|
101
|
+
throw new Error("the task's env gateway changed while the project was installed");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let singleton: TaskProjectOps | null = null;
|
|
106
|
+
|
|
107
|
+
export function taskProjectOps(): TaskProjectOps {
|
|
108
|
+
singleton ??= new TaskProjectOps({
|
|
109
|
+
journal: new TaskProjectJournalStore(taskUaiDir),
|
|
110
|
+
environment: async (taskId) => {
|
|
111
|
+
const task = getHostTask(taskId);
|
|
112
|
+
if (!task || task.statusMirror !== "running") return null;
|
|
113
|
+
return reconstructPersistedTaskEnvironment(task);
|
|
114
|
+
},
|
|
115
|
+
runIsCurrent,
|
|
116
|
+
inLifecycleSlot: (taskId, fn) => getOrchestrator().runTaskLifecycle(taskId, fn),
|
|
117
|
+
credentials: () => (credentialsMode() === "active" ? "cloud" : "own"),
|
|
118
|
+
installedGrant: (taskId, runEpoch) => {
|
|
119
|
+
const composer = activeCloudCredentials();
|
|
120
|
+
if (!composer) return null;
|
|
121
|
+
const view = composer.registry.currentView({ taskId, runEpoch });
|
|
122
|
+
return view
|
|
123
|
+
? { runEpoch, manifestRevision: view.manifestRevision, manifestDigest: view.manifestDigest }
|
|
124
|
+
: null;
|
|
125
|
+
},
|
|
126
|
+
envServes: (taskId, runEpoch, projectId) => {
|
|
127
|
+
const composer = activeCloudCredentials();
|
|
128
|
+
// The runner's own store serves every project it holds values for.
|
|
129
|
+
if (!composer) return true;
|
|
130
|
+
const view = composer.registry.currentView({ taskId, runEpoch });
|
|
131
|
+
if (!view || !view.projectIds.includes(projectId)) return false;
|
|
132
|
+
return composer.envSnapshot({ taskId, runEpoch }, view.projectIds) !== null;
|
|
133
|
+
},
|
|
134
|
+
liveProjectsSupported,
|
|
135
|
+
captureEnvSchema: (taskId, projectId, git) => captureTaskEnvSchemaFromClone(taskId, projectId, git),
|
|
136
|
+
storedEnvSchema: (taskId, projectId) => taskEnvSchemaObservation(taskId, projectId),
|
|
137
|
+
servedProjectIds: (taskId, runEpoch) => {
|
|
138
|
+
const composer = activeCloudCredentials();
|
|
139
|
+
if (!composer) return null;
|
|
140
|
+
const view = composer.registry.currentView({ taskId, runEpoch });
|
|
141
|
+
if (!view) return null;
|
|
142
|
+
return composer.envSnapshot({ taskId, runEpoch }, view.projectIds) !== null ? [...view.projectIds] : null;
|
|
143
|
+
},
|
|
144
|
+
installProjectEnv,
|
|
145
|
+
});
|
|
146
|
+
return singleton;
|
|
147
|
+
}
|