@action-llama/action-llama 0.3.0 → 0.4.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 +43 -102
- package/dist/agents/container-entry.js +123 -17
- package/dist/agents/container-entry.js.map +1 -1
- package/dist/agents/container-runner.d.ts +10 -4
- package/dist/agents/container-runner.d.ts.map +1 -1
- package/dist/agents/container-runner.js +83 -105
- package/dist/agents/container-runner.js.map +1 -1
- package/dist/agents/prompt.d.ts +2 -0
- package/dist/agents/prompt.d.ts.map +1 -1
- package/dist/agents/prompt.js +12 -4
- package/dist/agents/prompt.js.map +1 -1
- package/dist/agents/runner.d.ts +10 -1
- package/dist/agents/runner.d.ts.map +1 -1
- package/dist/agents/runner.js +60 -8
- package/dist/agents/runner.js.map +1 -1
- package/dist/cli/commands/{setup.d.ts → cloud-setup.d.ts} +1 -1
- package/dist/cli/commands/cloud-setup.d.ts.map +1 -0
- package/dist/cli/commands/cloud-setup.js +565 -0
- package/dist/cli/commands/cloud-setup.js.map +1 -0
- package/dist/cli/commands/cloud-teardown.d.ts +6 -0
- package/dist/cli/commands/cloud-teardown.d.ts.map +1 -0
- package/dist/cli/commands/cloud-teardown.js +152 -0
- package/dist/cli/commands/cloud-teardown.js.map +1 -0
- package/dist/cli/commands/console.d.ts.map +1 -1
- package/dist/cli/commands/console.js +108 -8
- package/dist/cli/commands/console.js.map +1 -1
- package/dist/cli/commands/creds.d.ts +2 -0
- package/dist/cli/commands/creds.d.ts.map +1 -0
- package/dist/cli/commands/creds.js +62 -0
- package/dist/cli/commands/creds.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +7 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +405 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/logs.d.ts +1 -0
- package/dist/cli/commands/logs.d.ts.map +1 -1
- package/dist/cli/commands/logs.js +67 -0
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/new.d.ts.map +1 -1
- package/dist/cli/commands/new.js +9 -2
- package/dist/cli/commands/new.js.map +1 -1
- package/dist/cli/commands/run.d.ts +6 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +121 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/start.d.ts +2 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +41 -14
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.d.ts +1 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +39 -2
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/main.js +57 -16
- package/dist/cli/main.js.map +1 -1
- package/dist/credentials/builtins/aws.d.ts +4 -0
- package/dist/credentials/builtins/aws.d.ts.map +1 -0
- package/dist/credentials/builtins/aws.js +33 -0
- package/dist/credentials/builtins/aws.js.map +1 -0
- package/dist/credentials/builtins/bugsnag-token.d.ts +4 -0
- package/dist/credentials/builtins/bugsnag-token.d.ts.map +1 -0
- package/dist/credentials/builtins/bugsnag-token.js +18 -0
- package/dist/credentials/builtins/bugsnag-token.js.map +1 -0
- package/dist/credentials/builtins/github-webhook-secret.d.ts.map +1 -1
- package/dist/credentials/builtins/github-webhook-secret.js +2 -1
- package/dist/credentials/builtins/github-webhook-secret.js.map +1 -1
- package/dist/credentials/builtins/index.d.ts.map +1 -1
- package/dist/credentials/builtins/index.js +10 -0
- package/dist/credentials/builtins/index.js.map +1 -1
- package/dist/credentials/builtins/netlify-token.d.ts +4 -0
- package/dist/credentials/builtins/netlify-token.d.ts.map +1 -0
- package/dist/credentials/builtins/netlify-token.js +18 -0
- package/dist/credentials/builtins/netlify-token.js.map +1 -0
- package/dist/credentials/builtins/openai-key.d.ts +4 -0
- package/dist/credentials/builtins/openai-key.d.ts.map +1 -0
- package/dist/credentials/builtins/openai-key.js +38 -0
- package/dist/credentials/builtins/openai-key.js.map +1 -0
- package/dist/credentials/builtins/x-twitter-api.d.ts +4 -0
- package/dist/credentials/builtins/x-twitter-api.d.ts.map +1 -0
- package/dist/credentials/builtins/x-twitter-api.js +28 -0
- package/dist/credentials/builtins/x-twitter-api.js.map +1 -0
- package/dist/credentials/prompter.d.ts.map +1 -1
- package/dist/credentials/prompter.js +8 -5
- package/dist/credentials/prompter.js.map +1 -1
- package/dist/docker/cloud-run-runtime.d.ts +61 -0
- package/dist/docker/cloud-run-runtime.d.ts.map +1 -0
- package/dist/docker/cloud-run-runtime.js +510 -0
- package/dist/docker/cloud-run-runtime.js.map +1 -0
- package/dist/docker/ecs-runtime.d.ts +73 -0
- package/dist/docker/ecs-runtime.d.ts.map +1 -0
- package/dist/docker/ecs-runtime.js +596 -0
- package/dist/docker/ecs-runtime.js.map +1 -0
- package/dist/docker/image.d.ts.map +1 -1
- package/dist/docker/image.js +3 -2
- package/dist/docker/image.js.map +1 -1
- package/dist/docker/local-runtime.d.ts +19 -0
- package/dist/docker/local-runtime.d.ts.map +1 -0
- package/dist/docker/local-runtime.js +209 -0
- package/dist/docker/local-runtime.js.map +1 -0
- package/dist/docker/network.d.ts +1 -1
- package/dist/docker/network.d.ts.map +1 -1
- package/dist/docker/network.js +2 -1
- package/dist/docker/network.js.map +1 -1
- package/dist/docker/runtime.d.ts +90 -0
- package/dist/docker/runtime.d.ts.map +1 -0
- package/dist/docker/runtime.js +2 -0
- package/dist/docker/runtime.js.map +1 -0
- package/dist/gateway/index.d.ts +8 -2
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +16 -8
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/routes/credentials.d.ts +5 -0
- package/dist/gateway/routes/credentials.d.ts.map +1 -0
- package/dist/gateway/routes/credentials.js +17 -0
- package/dist/gateway/routes/credentials.js.map +1 -0
- package/dist/gateway/routes/logs.d.ts +5 -0
- package/dist/gateway/routes/logs.d.ts.map +1 -0
- package/dist/gateway/routes/logs.js +31 -0
- package/dist/gateway/routes/logs.js.map +1 -0
- package/dist/gateway/routes/shutdown.d.ts +2 -1
- package/dist/gateway/routes/shutdown.d.ts.map +1 -1
- package/dist/gateway/routes/shutdown.js +7 -16
- package/dist/gateway/routes/shutdown.js.map +1 -1
- package/dist/gateway/routes/webhooks.d.ts +2 -1
- package/dist/gateway/routes/webhooks.d.ts.map +1 -1
- package/dist/gateway/routes/webhooks.js +11 -4
- package/dist/gateway/routes/webhooks.js.map +1 -1
- package/dist/gateway/types.d.ts +6 -0
- package/dist/gateway/types.d.ts.map +1 -0
- package/dist/gateway/types.js +2 -0
- package/dist/gateway/types.js.map +1 -0
- package/dist/scheduler/index.d.ts +3 -2
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +286 -67
- package/dist/scheduler/index.js.map +1 -1
- package/dist/setup/scaffold.d.ts.map +1 -1
- package/dist/setup/scaffold.js +110 -50
- package/dist/setup/scaffold.js.map +1 -1
- package/dist/setup/validators.d.ts +14 -0
- package/dist/setup/validators.d.ts.map +1 -1
- package/dist/setup/validators.js +53 -0
- package/dist/setup/validators.js.map +1 -1
- package/dist/shared/asm-backend.d.ts +25 -0
- package/dist/shared/asm-backend.d.ts.map +1 -0
- package/dist/shared/asm-backend.js +107 -0
- package/dist/shared/asm-backend.js.map +1 -0
- package/dist/shared/aws-constants.d.ts +55 -0
- package/dist/shared/aws-constants.d.ts.map +1 -0
- package/dist/shared/aws-constants.js +55 -0
- package/dist/shared/aws-constants.js.map +1 -0
- package/dist/shared/config.d.ts +25 -5
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js +15 -22
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/credential-backend.d.ts +28 -0
- package/dist/shared/credential-backend.d.ts.map +1 -0
- package/dist/shared/credential-backend.js +2 -0
- package/dist/shared/credential-backend.js.map +1 -0
- package/dist/shared/credentials.d.ts +42 -4
- package/dist/shared/credentials.d.ts.map +1 -1
- package/dist/shared/credentials.js +83 -6
- package/dist/shared/credentials.js.map +1 -1
- package/dist/shared/filesystem-backend.d.ts +18 -0
- package/dist/shared/filesystem-backend.d.ts.map +1 -0
- package/dist/shared/filesystem-backend.js +86 -0
- package/dist/shared/filesystem-backend.js.map +1 -0
- package/dist/shared/gsm-backend.d.ts +35 -0
- package/dist/shared/gsm-backend.d.ts.map +1 -0
- package/dist/shared/gsm-backend.js +208 -0
- package/dist/shared/gsm-backend.js.map +1 -0
- package/dist/shared/remote.d.ts +11 -0
- package/dist/shared/remote.d.ts.map +1 -0
- package/dist/shared/remote.js +29 -0
- package/dist/shared/remote.js.map +1 -0
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +13 -4
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/status-tracker.d.ts +3 -2
- package/dist/tui/status-tracker.d.ts.map +1 -1
- package/dist/tui/status-tracker.js.map +1 -1
- package/dist/webhooks/definitions/github.js +1 -1
- package/dist/webhooks/definitions/github.js.map +1 -1
- package/dist/webhooks/definitions/sentry.js +1 -1
- package/dist/webhooks/definitions/sentry.js.map +1 -1
- package/dist/webhooks/providers/github.d.ts +1 -1
- package/dist/webhooks/providers/github.d.ts.map +1 -1
- package/dist/webhooks/providers/github.js +13 -9
- package/dist/webhooks/providers/github.js.map +1 -1
- package/dist/webhooks/providers/sentry.d.ts +1 -1
- package/dist/webhooks/providers/sentry.d.ts.map +1 -1
- package/dist/webhooks/providers/sentry.js +12 -9
- package/dist/webhooks/providers/sentry.js.map +1 -1
- package/dist/webhooks/registry.d.ts +1 -1
- package/dist/webhooks/registry.d.ts.map +1 -1
- package/dist/webhooks/registry.js +20 -13
- package/dist/webhooks/registry.js.map +1 -1
- package/dist/webhooks/types.d.ts +16 -6
- package/dist/webhooks/types.d.ts.map +1 -1
- package/docker/Dockerfile +4 -1
- package/package.json +10 -1
- package/dist/cli/commands/setup.d.ts.map +0 -1
- package/dist/cli/commands/setup.js +0 -50
- package/dist/cli/commands/setup.js.map +0 -1
- package/dist/docker/container.d.ts +0 -19
- package/dist/docker/container.d.ts.map +0 -1
- package/dist/docker/container.js +0 -73
- package/dist/docker/container.js.map +0 -1
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { parseCredentialRef } from "../shared/credentials.js";
|
|
3
|
+
import { AWS_CONSTANTS } from "../shared/aws-constants.js";
|
|
4
|
+
/**
|
|
5
|
+
* GCP Cloud Run Jobs runtime.
|
|
6
|
+
*
|
|
7
|
+
* Launches agents as Cloud Run job executions with GSM secrets mounted
|
|
8
|
+
* as files at /credentials/<type>/<instance>/<field>.
|
|
9
|
+
*
|
|
10
|
+
* Auth resolution order (same as GoogleSecretManagerBackend):
|
|
11
|
+
* 1. GCP_SERVICE_ACCOUNT_KEY env var (JSON key — CI/Railway)
|
|
12
|
+
* 2. GOOGLE_APPLICATION_CREDENTIALS env var (file path)
|
|
13
|
+
* 3. gcloud auth application-default login (local dev)
|
|
14
|
+
*
|
|
15
|
+
* The runtime SA (your machine) needs:
|
|
16
|
+
* - run.jobs.create, run.jobs.run, run.jobs.get
|
|
17
|
+
* - run.executions.get, run.executions.cancel
|
|
18
|
+
* - artifactregistry.repositories.uploadArtifacts (for pushImage)
|
|
19
|
+
*
|
|
20
|
+
* The job SA (container) needs per-agent:
|
|
21
|
+
* - secretmanager.secretAccessor on its specific secrets
|
|
22
|
+
*/
|
|
23
|
+
export class CloudRunJobRuntime {
|
|
24
|
+
needsGateway = false;
|
|
25
|
+
config;
|
|
26
|
+
prefix;
|
|
27
|
+
accessToken;
|
|
28
|
+
tokenExpiry = 0;
|
|
29
|
+
constructor(config) {
|
|
30
|
+
this.config = config;
|
|
31
|
+
this.prefix = config.secretPrefix || AWS_CONSTANTS.DEFAULT_SECRET_PREFIX;
|
|
32
|
+
}
|
|
33
|
+
// --- Agent tracking ---
|
|
34
|
+
async isAgentRunning(agentName) {
|
|
35
|
+
const jobName = AWS_CONSTANTS.agentFamily(agentName);
|
|
36
|
+
const { gcpProject, region } = this.config;
|
|
37
|
+
const fullName = `projects/${gcpProject}/locations/${region}/jobs/${jobName}`;
|
|
38
|
+
try {
|
|
39
|
+
// List recent executions for this job
|
|
40
|
+
const res = await this.gcpRequest("GET", `https://run.googleapis.com/v2/${fullName}/executions?pageSize=1`);
|
|
41
|
+
if (!res.ok)
|
|
42
|
+
return false;
|
|
43
|
+
const data = await res.json();
|
|
44
|
+
const latest = data.executions?.[0];
|
|
45
|
+
// If the latest execution has no completionTime, it's still running
|
|
46
|
+
return !!latest && !latest.completionTime;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async listRunningAgents() {
|
|
53
|
+
const { gcpProject, region } = this.config;
|
|
54
|
+
const parent = `projects/${gcpProject}/locations/${region}`;
|
|
55
|
+
const jobsRes = await this.gcpRequest("GET", `https://run.googleapis.com/v2/${parent}/jobs?pageSize=100`);
|
|
56
|
+
if (!jobsRes.ok)
|
|
57
|
+
return [];
|
|
58
|
+
const jobsData = await jobsRes.json();
|
|
59
|
+
const jobs = (jobsData.jobs ?? []).filter((j) => {
|
|
60
|
+
const name = j.name.split("/").pop() ?? "";
|
|
61
|
+
return name.startsWith(AWS_CONSTANTS.CONTAINER_FILTER);
|
|
62
|
+
});
|
|
63
|
+
const running = [];
|
|
64
|
+
for (const job of jobs) {
|
|
65
|
+
const jobName = job.name.split("/").pop();
|
|
66
|
+
const agentName = AWS_CONSTANTS.agentNameFromFamily(jobName);
|
|
67
|
+
const execRes = await this.gcpRequest("GET", `https://run.googleapis.com/v2/${job.name}/executions?pageSize=1`);
|
|
68
|
+
if (!execRes.ok)
|
|
69
|
+
continue;
|
|
70
|
+
const execData = await execRes.json();
|
|
71
|
+
const latest = execData.executions?.[0];
|
|
72
|
+
if (latest && !latest.completionTime) {
|
|
73
|
+
running.push({
|
|
74
|
+
agentName,
|
|
75
|
+
taskId: latest.name.split("/").pop() ?? "unknown",
|
|
76
|
+
status: "RUNNING",
|
|
77
|
+
startedAt: latest.createTime ? new Date(latest.createTime) : undefined,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return running;
|
|
82
|
+
}
|
|
83
|
+
// --- Credential preparation ---
|
|
84
|
+
async prepareCredentials(credRefs) {
|
|
85
|
+
const mounts = [];
|
|
86
|
+
for (const credRef of credRefs) {
|
|
87
|
+
const { type, instance } = parseCredentialRef(credRef);
|
|
88
|
+
// List all fields for this credential by querying GSM
|
|
89
|
+
const fields = await this.listSecretFields(type, instance);
|
|
90
|
+
for (const field of fields) {
|
|
91
|
+
const secretName = this.gsmSecretName(type, instance, field);
|
|
92
|
+
mounts.push({
|
|
93
|
+
secretId: secretName,
|
|
94
|
+
mountPath: `/credentials/${type}/${instance}/${field}`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { strategy: "secrets-manager", mounts };
|
|
99
|
+
}
|
|
100
|
+
cleanupCredentials(_creds) {
|
|
101
|
+
// No-op — cloud secrets don't need cleanup
|
|
102
|
+
}
|
|
103
|
+
// --- Image management ---
|
|
104
|
+
async buildImage(opts) {
|
|
105
|
+
const remoteTag = `${this.config.artifactRegistry}/${opts.tag}`;
|
|
106
|
+
// Use Cloud Build — no local Docker needed
|
|
107
|
+
// Submits the build context to Cloud Build which builds and pushes in one step
|
|
108
|
+
opts.onProgress?.("Submitting to Cloud Build");
|
|
109
|
+
execFileSync("gcloud", [
|
|
110
|
+
"builds", "submit",
|
|
111
|
+
"--tag", remoteTag,
|
|
112
|
+
"--gcs-log-dir", `gs://${this.config.gcpProject}_cloudbuild/logs`,
|
|
113
|
+
"--project", this.config.gcpProject,
|
|
114
|
+
"--region", this.config.region,
|
|
115
|
+
"--quiet",
|
|
116
|
+
], {
|
|
117
|
+
encoding: "utf-8",
|
|
118
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
119
|
+
timeout: 600_000, // 10 min for cloud builds
|
|
120
|
+
cwd: opts.contextDir,
|
|
121
|
+
});
|
|
122
|
+
return remoteTag;
|
|
123
|
+
}
|
|
124
|
+
async pushImage(localImage) {
|
|
125
|
+
const remoteTag = `${this.config.artifactRegistry}/${localImage}`;
|
|
126
|
+
// Tag and push the local image to Artifact Registry
|
|
127
|
+
this.dockerExec("tag", localImage, remoteTag);
|
|
128
|
+
this.dockerExec("push", remoteTag);
|
|
129
|
+
return remoteTag;
|
|
130
|
+
}
|
|
131
|
+
// --- Container lifecycle ---
|
|
132
|
+
async launch(opts) {
|
|
133
|
+
const jobName = AWS_CONSTANTS.agentFamily(opts.agentName);
|
|
134
|
+
// Build the job spec with secret volume mounts
|
|
135
|
+
const secretMounts = opts.credentials.strategy === "secrets-manager"
|
|
136
|
+
? opts.credentials.mounts
|
|
137
|
+
: [];
|
|
138
|
+
// Use per-agent SA if available (created by `al doctor -c`),
|
|
139
|
+
// otherwise fall back to the shared SA from config
|
|
140
|
+
const perAgentSa = AWS_CONSTANTS.serviceAccountEmail(opts.agentName, this.config.gcpProject);
|
|
141
|
+
const serviceAccount = opts.serviceAccount || perAgentSa;
|
|
142
|
+
// Create or update the Cloud Run job
|
|
143
|
+
await this.createOrUpdateJob(jobName, {
|
|
144
|
+
image: opts.image,
|
|
145
|
+
env: opts.env,
|
|
146
|
+
secretMounts,
|
|
147
|
+
memory: opts.memory || "4Gi",
|
|
148
|
+
cpus: String(opts.cpus || 2),
|
|
149
|
+
serviceAccount,
|
|
150
|
+
});
|
|
151
|
+
// Execute the job and return the execution name
|
|
152
|
+
const executionName = await this.executeJob(jobName);
|
|
153
|
+
return executionName;
|
|
154
|
+
}
|
|
155
|
+
streamLogs(executionName, onLine, onStderr) {
|
|
156
|
+
let stopped = false;
|
|
157
|
+
let lastTimestamp;
|
|
158
|
+
const poll = async () => {
|
|
159
|
+
while (!stopped) {
|
|
160
|
+
try {
|
|
161
|
+
const entries = await this.readLogs(executionName, lastTimestamp);
|
|
162
|
+
for (const entry of entries) {
|
|
163
|
+
if (entry.timestamp)
|
|
164
|
+
lastTimestamp = entry.timestamp;
|
|
165
|
+
if (entry.textPayload) {
|
|
166
|
+
onLine(entry.textPayload);
|
|
167
|
+
}
|
|
168
|
+
else if (entry.jsonPayload) {
|
|
169
|
+
onLine(JSON.stringify(entry.jsonPayload));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
if (!stopped && onStderr) {
|
|
175
|
+
onStderr(`Log polling error: ${err.message}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Cloud Logging has ~5-15s ingestion delay
|
|
179
|
+
if (!stopped)
|
|
180
|
+
await sleep(5000);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
poll();
|
|
184
|
+
return {
|
|
185
|
+
stop: () => { stopped = true; },
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
async waitForExit(executionName, timeoutSeconds) {
|
|
189
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
190
|
+
while (Date.now() < deadline) {
|
|
191
|
+
const status = await this.getExecutionStatus(executionName);
|
|
192
|
+
if (status.succeeded)
|
|
193
|
+
return 0;
|
|
194
|
+
if (status.failed)
|
|
195
|
+
return 1;
|
|
196
|
+
if (status.cancelled)
|
|
197
|
+
return 130;
|
|
198
|
+
await sleep(5000);
|
|
199
|
+
}
|
|
200
|
+
// Timeout — cancel the execution
|
|
201
|
+
await this.kill(executionName);
|
|
202
|
+
throw new Error(`Cloud Run execution ${executionName} timed out after ${timeoutSeconds}s`);
|
|
203
|
+
}
|
|
204
|
+
async kill(executionName) {
|
|
205
|
+
try {
|
|
206
|
+
await this.gcpRequest("POST", `https://run.googleapis.com/v2/${executionName}:cancel`, {});
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// Execution may already be finished
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async remove(_executionName) {
|
|
213
|
+
// Cloud Run auto-cleans up executions
|
|
214
|
+
}
|
|
215
|
+
async fetchLogs(agentName, limit) {
|
|
216
|
+
const jobName = AWS_CONSTANTS.agentFamily(agentName);
|
|
217
|
+
const token = await this.getAccessToken();
|
|
218
|
+
const res = await fetch("https://logging.googleapis.com/v2/entries:list", {
|
|
219
|
+
method: "POST",
|
|
220
|
+
headers: {
|
|
221
|
+
Authorization: `Bearer ${token}`,
|
|
222
|
+
"Content-Type": "application/json",
|
|
223
|
+
},
|
|
224
|
+
body: JSON.stringify({
|
|
225
|
+
resourceNames: [`projects/${this.config.gcpProject}`],
|
|
226
|
+
filter: `resource.type="cloud_run_job" AND labels."run.googleapis.com/job_name"="${jobName}"`,
|
|
227
|
+
orderBy: "timestamp desc",
|
|
228
|
+
pageSize: limit,
|
|
229
|
+
}),
|
|
230
|
+
});
|
|
231
|
+
if (!res.ok) {
|
|
232
|
+
const body = await res.text();
|
|
233
|
+
throw new Error(`Cloud Logging read failed: ${res.status} ${body}`);
|
|
234
|
+
}
|
|
235
|
+
const data = await res.json();
|
|
236
|
+
return (data.entries ?? [])
|
|
237
|
+
.reverse()
|
|
238
|
+
.map((e) => e.textPayload ?? (e.jsonPayload ? JSON.stringify(e.jsonPayload) : ""))
|
|
239
|
+
.filter(Boolean);
|
|
240
|
+
}
|
|
241
|
+
// --- Internal: GCP API helpers ---
|
|
242
|
+
gsmSecretName(type, instance, field) {
|
|
243
|
+
return `${this.prefix}--${type}--${instance}--${field}`;
|
|
244
|
+
}
|
|
245
|
+
async listSecretFields(type, instance) {
|
|
246
|
+
const prefix = `${this.prefix}--${type}--${instance}--`;
|
|
247
|
+
const token = await this.getAccessToken();
|
|
248
|
+
const url = `https://secretmanager.googleapis.com/v1/projects/${this.config.gcpProject}/secrets?filter=name:${encodeURIComponent(prefix)}`;
|
|
249
|
+
const res = await fetch(url, {
|
|
250
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
251
|
+
});
|
|
252
|
+
if (!res.ok) {
|
|
253
|
+
const body = await res.text();
|
|
254
|
+
throw new Error(`Failed to list GSM secrets for ${type}:${instance}: ${res.status} ${body}`);
|
|
255
|
+
}
|
|
256
|
+
const data = await res.json();
|
|
257
|
+
const fields = [];
|
|
258
|
+
for (const secret of data.secrets || []) {
|
|
259
|
+
const secretId = secret.name.split("/").pop();
|
|
260
|
+
const parts = secretId.split("--");
|
|
261
|
+
if (parts.length === 4 && parts[0] === this.prefix && parts[1] === type && parts[2] === instance) {
|
|
262
|
+
fields.push(parts[3]);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return fields;
|
|
266
|
+
}
|
|
267
|
+
async createOrUpdateJob(jobName, opts) {
|
|
268
|
+
const { gcpProject, region } = this.config;
|
|
269
|
+
const parent = `projects/${gcpProject}/locations/${region}`;
|
|
270
|
+
const fullName = `${parent}/jobs/${jobName}`;
|
|
271
|
+
// Build volume mounts and volumes from secret mounts
|
|
272
|
+
const volumes = [];
|
|
273
|
+
const volumeMounts = [];
|
|
274
|
+
for (let i = 0; i < opts.secretMounts.length; i++) {
|
|
275
|
+
const mount = opts.secretMounts[i];
|
|
276
|
+
const volName = `secret-${i}`;
|
|
277
|
+
volumes.push({
|
|
278
|
+
name: volName,
|
|
279
|
+
secret: {
|
|
280
|
+
secret: `projects/${gcpProject}/secrets/${mount.secretId}`,
|
|
281
|
+
items: [{ version: "latest", path: mount.mountPath.split("/").pop() }],
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
// Mount the volume at the parent directory of the target path
|
|
285
|
+
const parentDir = mount.mountPath.split("/").slice(0, -1).join("/");
|
|
286
|
+
volumeMounts.push({ name: volName, mountPath: parentDir });
|
|
287
|
+
}
|
|
288
|
+
// Deduplicate volume mounts with the same mountPath — Cloud Run only allows
|
|
289
|
+
// one mount per path, so we need to use a single volume per directory
|
|
290
|
+
const mountsByDir = new Map();
|
|
291
|
+
for (const mount of opts.secretMounts) {
|
|
292
|
+
const dir = mount.mountPath.split("/").slice(0, -1).join("/");
|
|
293
|
+
if (!mountsByDir.has(dir))
|
|
294
|
+
mountsByDir.set(dir, []);
|
|
295
|
+
mountsByDir.get(dir).push(mount);
|
|
296
|
+
}
|
|
297
|
+
// Rebuild volumes/mounts properly — one volume per unique directory
|
|
298
|
+
volumes.length = 0;
|
|
299
|
+
volumeMounts.length = 0;
|
|
300
|
+
let volIdx = 0;
|
|
301
|
+
for (const [dir, mounts] of mountsByDir) {
|
|
302
|
+
const volName = `secrets-${volIdx++}`;
|
|
303
|
+
volumes.push({
|
|
304
|
+
name: volName,
|
|
305
|
+
secret: {
|
|
306
|
+
// For multi-file secret volumes, use items to map each secret
|
|
307
|
+
// Cloud Run requires using secret references
|
|
308
|
+
items: mounts.map((m) => ({
|
|
309
|
+
version: "latest",
|
|
310
|
+
path: m.mountPath.split("/").pop(),
|
|
311
|
+
secret: `projects/${gcpProject}/secrets/${m.secretId}`,
|
|
312
|
+
})),
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
volumeMounts.push({ name: volName, mountPath: dir });
|
|
316
|
+
}
|
|
317
|
+
const envVars = Object.entries(opts.env).map(([name, value]) => ({ name, value }));
|
|
318
|
+
// Derive timeout from TIMEOUT_SECONDS env var (set by container-runner)
|
|
319
|
+
const timeoutSeconds = opts.env.TIMEOUT_SECONDS || "3600";
|
|
320
|
+
const jobSpec = {
|
|
321
|
+
template: {
|
|
322
|
+
template: {
|
|
323
|
+
containers: [{
|
|
324
|
+
image: opts.image,
|
|
325
|
+
env: envVars,
|
|
326
|
+
resources: {
|
|
327
|
+
limits: {
|
|
328
|
+
memory: opts.memory,
|
|
329
|
+
cpu: opts.cpus,
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
volumeMounts,
|
|
333
|
+
}],
|
|
334
|
+
volumes,
|
|
335
|
+
serviceAccount: opts.serviceAccount,
|
|
336
|
+
timeout: `${timeoutSeconds}s`,
|
|
337
|
+
maxRetries: 0,
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
// Try to update existing job, create if not found
|
|
342
|
+
const updateRes = await this.gcpRequest("PATCH", `https://run.googleapis.com/v2/${fullName}`, jobSpec);
|
|
343
|
+
if (updateRes.status === 404) {
|
|
344
|
+
await updateRes.text(); // drain
|
|
345
|
+
const createRes = await this.gcpRequest("POST", `https://run.googleapis.com/v2/${parent}/jobs?jobId=${jobName}`, jobSpec);
|
|
346
|
+
if (!createRes.ok) {
|
|
347
|
+
const body = await createRes.text();
|
|
348
|
+
throw new Error(`Failed to create Cloud Run job ${jobName}: ${createRes.status} ${body}`);
|
|
349
|
+
}
|
|
350
|
+
await createRes.text(); // drain
|
|
351
|
+
}
|
|
352
|
+
else if (!updateRes.ok) {
|
|
353
|
+
const body = await updateRes.text();
|
|
354
|
+
throw new Error(`Failed to update Cloud Run job ${jobName}: ${updateRes.status} ${body}`);
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
await updateRes.text(); // drain
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
async executeJob(jobName) {
|
|
361
|
+
const { gcpProject, region } = this.config;
|
|
362
|
+
const fullName = `projects/${gcpProject}/locations/${region}/jobs/${jobName}`;
|
|
363
|
+
const res = await this.gcpRequest("POST", `https://run.googleapis.com/v2/${fullName}:run`, {});
|
|
364
|
+
if (!res.ok) {
|
|
365
|
+
const body = await res.text();
|
|
366
|
+
throw new Error(`Failed to execute Cloud Run job ${jobName}: ${res.status} ${body}`);
|
|
367
|
+
}
|
|
368
|
+
const data = await res.json();
|
|
369
|
+
// The response is an Operation; the execution name is in metadata or name
|
|
370
|
+
return data.metadata?.name || data.name || fullName;
|
|
371
|
+
}
|
|
372
|
+
async getExecutionStatus(executionName) {
|
|
373
|
+
const res = await this.gcpRequest("GET", `https://run.googleapis.com/v2/${executionName}`);
|
|
374
|
+
if (!res.ok) {
|
|
375
|
+
const body = await res.text();
|
|
376
|
+
throw new Error(`Failed to get execution status: ${res.status} ${body}`);
|
|
377
|
+
}
|
|
378
|
+
const data = await res.json();
|
|
379
|
+
// Check terminal conditions
|
|
380
|
+
const completed = data.conditions?.find((c) => c.type === "Completed");
|
|
381
|
+
if (!completed || completed.state !== "CONDITION_SUCCEEDED") {
|
|
382
|
+
// Not done yet — check if explicitly failed or cancelled
|
|
383
|
+
return {
|
|
384
|
+
succeeded: false,
|
|
385
|
+
failed: (data.failedCount ?? 0) > 0,
|
|
386
|
+
cancelled: (data.cancelledCount ?? 0) > 0,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
succeeded: (data.succeededCount ?? 0) > 0,
|
|
391
|
+
failed: (data.failedCount ?? 0) > 0,
|
|
392
|
+
cancelled: (data.cancelledCount ?? 0) > 0,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
async readLogs(executionName, afterTimestamp) {
|
|
396
|
+
const token = await this.getAccessToken();
|
|
397
|
+
// Extract execution short name for the filter
|
|
398
|
+
const execShortName = executionName.split("/").pop();
|
|
399
|
+
let filter = `resource.type="cloud_run_job" AND labels."run.googleapis.com/execution_name"="${execShortName}"`;
|
|
400
|
+
if (afterTimestamp) {
|
|
401
|
+
filter += ` AND timestamp>"${afterTimestamp}"`;
|
|
402
|
+
}
|
|
403
|
+
const params = new URLSearchParams({
|
|
404
|
+
resourceNames: `projects/${this.config.gcpProject}`,
|
|
405
|
+
filter,
|
|
406
|
+
orderBy: "timestamp asc",
|
|
407
|
+
pageSize: "100",
|
|
408
|
+
});
|
|
409
|
+
const res = await fetch(`https://logging.googleapis.com/v2/entries:list`, {
|
|
410
|
+
method: "POST",
|
|
411
|
+
headers: {
|
|
412
|
+
Authorization: `Bearer ${token}`,
|
|
413
|
+
"Content-Type": "application/json",
|
|
414
|
+
},
|
|
415
|
+
body: JSON.stringify({
|
|
416
|
+
resourceNames: [`projects/${this.config.gcpProject}`],
|
|
417
|
+
filter,
|
|
418
|
+
orderBy: "timestamp asc",
|
|
419
|
+
pageSize: 100,
|
|
420
|
+
}),
|
|
421
|
+
});
|
|
422
|
+
if (!res.ok) {
|
|
423
|
+
const body = await res.text();
|
|
424
|
+
throw new Error(`Cloud Logging read failed: ${res.status} ${body}`);
|
|
425
|
+
}
|
|
426
|
+
const data = await res.json();
|
|
427
|
+
return data.entries || [];
|
|
428
|
+
}
|
|
429
|
+
// --- Internal: Auth ---
|
|
430
|
+
async getAccessToken() {
|
|
431
|
+
if (this.accessToken && Date.now() < this.tokenExpiry - 60_000) {
|
|
432
|
+
return this.accessToken;
|
|
433
|
+
}
|
|
434
|
+
// GCP_SERVICE_ACCOUNT_KEY env var (JSON key for CI/Railway)
|
|
435
|
+
const saKeyJson = process.env.GCP_SERVICE_ACCOUNT_KEY;
|
|
436
|
+
if (saKeyJson) {
|
|
437
|
+
return this.getTokenFromServiceAccountKey(JSON.parse(saKeyJson));
|
|
438
|
+
}
|
|
439
|
+
// Fall back to gcloud ADC
|
|
440
|
+
return this.getTokenFromGcloud();
|
|
441
|
+
}
|
|
442
|
+
async getTokenFromServiceAccountKey(key) {
|
|
443
|
+
const { createSign } = await import("crypto");
|
|
444
|
+
const header = Buffer.from(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString("base64url");
|
|
445
|
+
const now = Math.floor(Date.now() / 1000);
|
|
446
|
+
const claims = Buffer.from(JSON.stringify({
|
|
447
|
+
iss: key.client_email,
|
|
448
|
+
scope: "https://www.googleapis.com/auth/cloud-platform",
|
|
449
|
+
aud: key.token_uri,
|
|
450
|
+
iat: now,
|
|
451
|
+
exp: now + 3600,
|
|
452
|
+
})).toString("base64url");
|
|
453
|
+
const signer = createSign("RSA-SHA256");
|
|
454
|
+
signer.update(`${header}.${claims}`);
|
|
455
|
+
const signature = signer.sign(key.private_key, "base64url");
|
|
456
|
+
const jwt = `${header}.${claims}.${signature}`;
|
|
457
|
+
const res = await fetch(key.token_uri, {
|
|
458
|
+
method: "POST",
|
|
459
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
460
|
+
body: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${jwt}`,
|
|
461
|
+
});
|
|
462
|
+
if (!res.ok) {
|
|
463
|
+
const body = await res.text();
|
|
464
|
+
throw new Error(`Failed to get access token: ${res.status} ${body}`);
|
|
465
|
+
}
|
|
466
|
+
const data = await res.json();
|
|
467
|
+
this.accessToken = data.access_token;
|
|
468
|
+
this.tokenExpiry = Date.now() + data.expires_in * 1000;
|
|
469
|
+
return this.accessToken;
|
|
470
|
+
}
|
|
471
|
+
async getTokenFromGcloud() {
|
|
472
|
+
try {
|
|
473
|
+
const token = execFileSync("gcloud", ["auth", "application-default", "print-access-token"], {
|
|
474
|
+
encoding: "utf-8",
|
|
475
|
+
timeout: 10_000,
|
|
476
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
477
|
+
}).trim();
|
|
478
|
+
this.accessToken = token;
|
|
479
|
+
this.tokenExpiry = Date.now() + 3500_000;
|
|
480
|
+
return token;
|
|
481
|
+
}
|
|
482
|
+
catch (err) {
|
|
483
|
+
throw new Error("Failed to get GCP access token. Either:\n" +
|
|
484
|
+
" 1. Set GCP_SERVICE_ACCOUNT_KEY env var with a service account JSON key, or\n" +
|
|
485
|
+
" 2. Run: gcloud auth application-default login\n" +
|
|
486
|
+
`Original error: ${err.message}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
async gcpRequest(method, url, body) {
|
|
490
|
+
const token = await this.getAccessToken();
|
|
491
|
+
return fetch(url, {
|
|
492
|
+
method,
|
|
493
|
+
headers: {
|
|
494
|
+
Authorization: `Bearer ${token}`,
|
|
495
|
+
"Content-Type": "application/json",
|
|
496
|
+
},
|
|
497
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
dockerExec(...args) {
|
|
501
|
+
return execFileSync("docker", args, {
|
|
502
|
+
encoding: "utf-8",
|
|
503
|
+
timeout: 300_000, // 5 min for push
|
|
504
|
+
}).trim();
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function sleep(ms) {
|
|
508
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
509
|
+
}
|
|
510
|
+
//# sourceMappingURL=cloud-run-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-run-runtime.js","sourceRoot":"","sources":["../../src/docker/cloud-run-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ContainerRuntime, RuntimeLaunchOpts, RuntimeCredentials, BuildImageOpts, RunningAgent } from "./runtime.js";
|
|
2
|
+
export interface ECSFargateConfig {
|
|
3
|
+
awsRegion: string;
|
|
4
|
+
ecsCluster: string;
|
|
5
|
+
ecrRepository: string;
|
|
6
|
+
executionRoleArn: string;
|
|
7
|
+
taskRoleArn: string;
|
|
8
|
+
subnets: string[];
|
|
9
|
+
securityGroups?: string[];
|
|
10
|
+
secretPrefix?: string;
|
|
11
|
+
buildBucket?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* AWS ECS Fargate runtime.
|
|
15
|
+
*
|
|
16
|
+
* Launches agents as ECS Fargate tasks with AWS Secrets Manager secrets
|
|
17
|
+
* injected as environment variables or mounted via container definitions.
|
|
18
|
+
*
|
|
19
|
+
* Auth: AWS SDK default credential provider chain
|
|
20
|
+
* 1. AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars
|
|
21
|
+
* 2. AWS_PROFILE / ~/.aws/credentials
|
|
22
|
+
* 3. SSO / IAM instance role (EC2/ECS/Lambda)
|
|
23
|
+
*
|
|
24
|
+
* The runtime credentials (your machine) need:
|
|
25
|
+
* - ecs:RegisterTaskDefinition, ecs:RunTask, ecs:DescribeTasks, ecs:StopTask
|
|
26
|
+
* - ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, ecr:PutImage, etc.
|
|
27
|
+
* - logs:GetLogEvents
|
|
28
|
+
*
|
|
29
|
+
* The task role (container) needs per-agent:
|
|
30
|
+
* - secretsmanager:GetSecretValue on its specific secrets
|
|
31
|
+
*/
|
|
32
|
+
export declare class ECSFargateRuntime implements ContainerRuntime {
|
|
33
|
+
readonly needsGateway = false;
|
|
34
|
+
private config;
|
|
35
|
+
private prefix;
|
|
36
|
+
private ecsClient;
|
|
37
|
+
private smClient;
|
|
38
|
+
private logsClient;
|
|
39
|
+
private cbClient;
|
|
40
|
+
private s3Client;
|
|
41
|
+
private ecrClient;
|
|
42
|
+
constructor(config: ECSFargateConfig);
|
|
43
|
+
private static readonly STARTED_BY_PREFIX;
|
|
44
|
+
static readonly LOG_GROUP: string;
|
|
45
|
+
private logGroupCreated;
|
|
46
|
+
private ensureLogGroup;
|
|
47
|
+
isAgentRunning(agentName: string): Promise<boolean>;
|
|
48
|
+
listRunningAgents(): Promise<RunningAgent[]>;
|
|
49
|
+
prepareCredentials(credRefs: string[]): Promise<RuntimeCredentials>;
|
|
50
|
+
cleanupCredentials(_creds: RuntimeCredentials): void;
|
|
51
|
+
buildImage(opts: BuildImageOpts): Promise<string>;
|
|
52
|
+
pushImage(_localImage: string): Promise<string>;
|
|
53
|
+
private buildImageCodeBuild;
|
|
54
|
+
private ecrImageExists;
|
|
55
|
+
private ensureBuildBucket;
|
|
56
|
+
private ensureCodeBuildProject;
|
|
57
|
+
launch(opts: RuntimeLaunchOpts): Promise<string>;
|
|
58
|
+
streamLogs(taskArn: string, onLine: (line: string) => void, onStderr?: (text: string) => void): {
|
|
59
|
+
stop: () => void;
|
|
60
|
+
};
|
|
61
|
+
waitForExit(taskArn: string, timeoutSeconds: number): Promise<number>;
|
|
62
|
+
kill(taskArn: string): Promise<void>;
|
|
63
|
+
remove(_taskArn: string): Promise<void>;
|
|
64
|
+
fetchLogs(agentName: string, limit: number): Promise<string[]>;
|
|
65
|
+
private awsSecretName;
|
|
66
|
+
private listSecretFields;
|
|
67
|
+
private registerTaskDefinition;
|
|
68
|
+
private runTask;
|
|
69
|
+
private getLogEvents;
|
|
70
|
+
private deriveTaskRoleArn;
|
|
71
|
+
private getAccountId;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=ecs-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecs-runtime.d.ts","sourceRoot":"","sources":["../../src/docker/ecs-runtime.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAe,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIvI,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,iBAAkB,YAAW,gBAAgB;IACxD,QAAQ,CAAC,YAAY,SAAS;IAE9B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,SAAS,CAAY;gBAEjB,MAAM,EAAE,gBAAgB;IAapC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAA4B;IACrE,MAAM,CAAC,QAAQ,CAAC,SAAS,SAA2B;IACpD,OAAO,CAAC,eAAe,CAAS;YAElB,cAAc;IAYtB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUnD,iBAAiB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IA6B5C,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAmBzE,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAM9C,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjD,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAKvC,mBAAmB;YAmMnB,cAAc;YAgBd,iBAAiB;YAuBjB,sBAAsB;IA2C9B,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BtD,UAAU,CACR,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAC9B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAChC;QAAE,IAAI,EAAE,MAAM,IAAI,CAAA;KAAE;IAwCjB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBrE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAcpE,OAAO,CAAC,aAAa;YAIP,gBAAgB;YAoBhB,sBAAsB;YAwDtB,OAAO;YA0BP,YAAY;IAoB1B,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,YAAY;CAKrB"}
|