@xfey/tutti 0.1.119 → 0.1.121
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/approvals/decision-command.d.ts +2 -2
- package/dist/collaboration-state/clarification-snapshot.d.ts +9 -9
- package/dist/collaboration-state/task-compile-context.d.ts +1 -1
- package/dist/control-plane/workflows/openai.d.ts +3 -4
- package/dist/control-plane/workflows/openai.js +3 -2
- package/dist/providers/openai/app-server/invocation-coordinator.d.ts +1 -0
- package/dist/providers/openai/app-server/invocation-coordinator.js +4 -1
- package/dist/providers/openai/app-server/invocation-deadline.d.ts +3 -0
- package/dist/providers/openai/app-server/invocation-deadline.js +15 -0
- package/dist/providers/openai/app-server/read-only-procedure.d.ts +4 -2
- package/dist/providers/openai/app-server/read-only-procedure.js +16 -0
- package/dist/providers/openai/app-server/workspace-write-run.d.ts +4 -2
- package/dist/providers/openai/app-server/workspace-write-run.js +16 -0
- package/dist/providers/openai/chat-assistant.d.ts +3 -4
- package/dist/providers/openai/chat-assistant.js +2 -1
- package/dist/providers/openai/execution-access.d.ts +17 -0
- package/dist/providers/openai/execution-access.js +13 -0
- package/dist/providers/openai/sdk-procedure-runner.d.ts +2 -2
- package/dist/providers/openai/sdk-procedure-runner.js +17 -0
- package/dist/run-pipeline/artifact-applicability.d.ts +3 -4
- package/dist/run-pipeline/artifact-applicability.js +2 -1
- package/dist/run-pipeline/openai.d.ts +3 -4
- package/dist/run-pipeline/openai.js +3 -2
- package/dist/run-pipeline/task-run-invocation.js +6 -12
- package/dist/server-shell/cli/cli.js +3 -0
- package/dist/server-shell/cli/host-lifecycle.js +1 -0
- package/dist/server-shell/cli/host-server-runtime.d.ts +1 -0
- package/dist/server-shell/cli/host-server-runtime.js +83 -34
- package/dist/server-shell/cli/launch-command.js +1 -1
- package/dist/server-shell/cli/launch.d.ts +7 -3
- package/dist/server-shell/cli/launch.js +23 -4
- package/dist/server-shell/cli/machine-local.d.ts +9 -0
- package/dist/server-shell/cli/machine-local.js +60 -6
- package/dist/server-shell/cli/project-resolver.d.ts +2 -2
- package/dist/server-shell/cli/project-resolver.js +6 -3
- package/dist/server-shell/cli/relay-registration.js +38 -1
- package/dist/server-shell/http/routes/local-control.d.ts +1 -1
- package/dist/server-shell/http/routes/local-control.js +2 -46
- package/dist/server-shell/http/routes/project-api/openapi-workspace-routes.d.ts +45 -137
- package/dist/server-shell/http/routes/project-api/openapi.d.ts +45 -137
- package/dist/server-shell/http/routes/project-api/schemas.d.ts +24 -136
- package/dist/server-shell/http/routes/project-api/schemas.js +4 -58
- package/dist/server-shell/http/routes/project-api/types.d.ts +3 -0
- package/dist/server-shell/local-console/managed-project-routes.d.ts +9 -0
- package/dist/server-shell/local-console/managed-project-routes.js +120 -0
- package/dist/server-shell/local-console/managed-project-service.d.ts +141 -0
- package/dist/server-shell/local-console/managed-project-service.js +158 -0
- package/dist/server-shell/local-console/operation-coordinator.d.ts +1 -1
- package/dist/server-shell/local-console/package-update-hosts.js +2 -1
- package/dist/server-shell/local-console/project-service.d.ts +4 -1
- package/dist/server-shell/local-console/project-service.js +62 -14
- package/dist/server-shell/local-console/server.js +22 -2
- package/dist/server-shell/managed-access/execution-binding.d.ts +9 -0
- package/dist/server-shell/managed-access/execution-binding.js +22 -0
- package/dist/server-shell/managed-access/existing-project.d.ts +15 -0
- package/dist/server-shell/managed-access/existing-project.js +41 -0
- package/dist/server-shell/managed-access/legacy-records.d.ts +2 -0
- package/dist/server-shell/managed-access/legacy-records.js +24 -0
- package/dist/server-shell/managed-access/model-control-client.d.ts +65 -0
- package/dist/server-shell/managed-access/model-control-client.js +112 -0
- package/dist/server-shell/managed-access/private-store.d.ts +19 -0
- package/dist/server-shell/managed-access/private-store.js +275 -0
- package/dist/server-shell/managed-access/project-provider.d.ts +18 -0
- package/dist/server-shell/managed-access/project-provider.js +30 -0
- package/dist/server-shell/managed-access/records.d.ts +103 -0
- package/dist/server-shell/managed-access/records.js +74 -0
- package/dist/server-shell/managed-access/runners.d.ts +11 -0
- package/dist/server-shell/managed-access/runners.js +103 -0
- package/dist/server-shell/managed-access/runtime-records.d.ts +106 -0
- package/dist/server-shell/managed-access/runtime-records.js +65 -0
- package/dist/server-shell/managed-access/runtime.d.ts +48 -0
- package/dist/server-shell/managed-access/runtime.js +300 -0
- package/dist/server-shell/managed-access/state.d.ts +53 -0
- package/dist/server-shell/managed-access/state.js +292 -0
- package/dist/server-shell/managed-access/transport.d.ts +45 -0
- package/dist/server-shell/managed-access/transport.js +39 -0
- package/dist/server-shell/managed-access/workspace.d.ts +10 -0
- package/dist/server-shell/managed-access/workspace.js +69 -0
- package/dist/server-shell/smoke/e2e-client.d.ts +8 -3
- package/dist/server-shell/smoke/e2e-client.js +11 -11
- package/node_modules/@tutti/relay-client/dist/host-control.d.ts +4 -1
- package/node_modules/@tutti/relay-client/dist/host-control.js +26 -3
- package/node_modules/@tutti/relay-client/dist/index.d.ts +1 -0
- package/node_modules/@tutti/relay-client/dist/index.js +1 -0
- package/node_modules/@tutti/relay-client/dist/project-authority.d.ts +70 -0
- package/node_modules/@tutti/relay-client/dist/project-authority.js +139 -0
- package/node_modules/@tutti/shared/dist/ids/index.d.ts +7 -0
- package/node_modules/@tutti/shared/dist/ids/index.js +7 -0
- package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +1 -0
- package/node_modules/@tutti/shared/dist/schemas/api/index.js +1 -0
- package/node_modules/@tutti/shared/dist/schemas/api/managed-account.d.ts +34 -0
- package/node_modules/@tutti/shared/dist/schemas/api/managed-account.js +40 -0
- package/node_modules/@tutti/shared/dist/schemas/api/provider-config.d.ts +7 -4
- package/node_modules/@tutti/shared/dist/schemas/api/provider-config.js +5 -0
- package/node_modules/@tutti/shared/dist/schemas/api/runtime-events.d.ts +3 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/creation-validation.d.ts +26 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/creation-validation.js +40 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/index.d.ts +5 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/index.js +5 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/managed-account.d.ts +12 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/managed-account.js +13 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/managed-models.d.ts +17 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/managed-models.js +17 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/managed-runtime.d.ts +113 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/managed-runtime.js +84 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/project-authority.d.ts +114 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/project-authority.js +102 -0
- package/package.json +1 -1
- package/web/assets/{homepage-motion-scene-B6lCCHBq.js → homepage-motion-scene-WfLyzcCG.js} +1 -1
- package/web/assets/{index-DsYi7AhN.css → index-ATsYiBZs.css} +1 -1
- package/web/assets/index-o9YCtzEd.js +70 -0
- package/web/index.html +2 -2
- package/web/assets/index-DepsYMLl.js +0 -70
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { closeSync, constants, existsSync, fstatSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, readSync, realpathSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import Database from "better-sqlite3";
|
|
6
|
+
const MAX_PRIVATE_BYTES = 32 * 1024;
|
|
7
|
+
const packageRoot = realpathSync(fileURLToPath(new URL("../../../", import.meta.url)));
|
|
8
|
+
export class ManagedLocalStateError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
constructor(code) {
|
|
11
|
+
super(code);
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.name = "ManagedLocalStateError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function systemCode(error) {
|
|
17
|
+
return typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
18
|
+
}
|
|
19
|
+
function unlinkIfPresent(path) {
|
|
20
|
+
try {
|
|
21
|
+
unlinkSync(path);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (systemCode(error) !== "ENOENT")
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function isWithin(parent, target) {
|
|
29
|
+
const path = relative(parent, target);
|
|
30
|
+
return path === "" || (!path.startsWith("../") && path !== ".." && !isAbsolute(path));
|
|
31
|
+
}
|
|
32
|
+
function guard(run) {
|
|
33
|
+
try {
|
|
34
|
+
return run();
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error instanceof ManagedLocalStateError)
|
|
38
|
+
throw error;
|
|
39
|
+
throw new ManagedLocalStateError("managed_private_state_unavailable");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Ancestors such as /var -> /private/var may be OS aliases. The selected Home and
|
|
43
|
+
// every directory we own below it must be actual owner-only directories, not links.
|
|
44
|
+
export function ensureManagedPrivateRoot(tuttiHome, originHash) {
|
|
45
|
+
return guard(() => {
|
|
46
|
+
if (!isAbsolute(tuttiHome) || !/^[a-f0-9]{64}$/.test(originHash))
|
|
47
|
+
throw new ManagedLocalStateError("managed_private_directory_invalid");
|
|
48
|
+
let ancestor = tuttiHome;
|
|
49
|
+
while (!existsSync(ancestor) && dirname(ancestor) !== ancestor)
|
|
50
|
+
ancestor = dirname(ancestor);
|
|
51
|
+
const proposed = join(realpathSync(ancestor), relative(ancestor, tuttiHome));
|
|
52
|
+
if (isWithin(packageRoot, proposed))
|
|
53
|
+
throw new ManagedLocalStateError("managed_state_in_repository");
|
|
54
|
+
for (let path = proposed; dirname(path) !== path; path = dirname(path)) {
|
|
55
|
+
if (existsSync(join(path, ".git")))
|
|
56
|
+
throw new ManagedLocalStateError("managed_state_in_repository");
|
|
57
|
+
}
|
|
58
|
+
for (const path of [
|
|
59
|
+
tuttiHome,
|
|
60
|
+
join(tuttiHome, "credentials"),
|
|
61
|
+
join(tuttiHome, "credentials", "managed"),
|
|
62
|
+
join(tuttiHome, "credentials", "managed", originHash),
|
|
63
|
+
]) {
|
|
64
|
+
mkdirSync(path, { recursive: true, mode: 0o700 });
|
|
65
|
+
const stat = lstatSync(path);
|
|
66
|
+
if (!stat.isDirectory() ||
|
|
67
|
+
stat.isSymbolicLink() ||
|
|
68
|
+
stat.uid !== process.getuid?.() ||
|
|
69
|
+
stat.mode & 0o077)
|
|
70
|
+
throw new ManagedLocalStateError("managed_private_directory_invalid");
|
|
71
|
+
}
|
|
72
|
+
return realpathSync(join(tuttiHome, "credentials", "managed", originHash));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
export class ManagedPrivateStore {
|
|
76
|
+
root;
|
|
77
|
+
identity;
|
|
78
|
+
constructor(root) {
|
|
79
|
+
// Normalize OS ancestor aliases, but do not accept a linked selected directory.
|
|
80
|
+
if (guard(() => lstatSync(root).isSymbolicLink()))
|
|
81
|
+
throw new ManagedLocalStateError("managed_private_directory_invalid");
|
|
82
|
+
this.root = guard(() => realpathSync(root));
|
|
83
|
+
this.identity = guard(() => this.checkRoot());
|
|
84
|
+
}
|
|
85
|
+
checkRoot() {
|
|
86
|
+
const stat = lstatSync(this.root);
|
|
87
|
+
if (!stat.isDirectory() ||
|
|
88
|
+
stat.isSymbolicLink() ||
|
|
89
|
+
stat.uid !== process.getuid?.() ||
|
|
90
|
+
stat.mode & 0o077 ||
|
|
91
|
+
realpathSync(this.root) !== this.root ||
|
|
92
|
+
(this.identity !== undefined &&
|
|
93
|
+
(stat.dev !== this.identity.dev || stat.ino !== this.identity.ino)))
|
|
94
|
+
throw new ManagedLocalStateError("managed_private_directory_invalid");
|
|
95
|
+
return { dev: stat.dev, ino: stat.ino };
|
|
96
|
+
}
|
|
97
|
+
path(name) {
|
|
98
|
+
if (!/^[a-zA-Z0-9_-]{1,120}\.json$/.test(name))
|
|
99
|
+
throw new ManagedLocalStateError("managed_record_name_invalid");
|
|
100
|
+
return join(this.root, name);
|
|
101
|
+
}
|
|
102
|
+
read(name) {
|
|
103
|
+
return guard(() => {
|
|
104
|
+
this.checkRoot();
|
|
105
|
+
let fd;
|
|
106
|
+
try {
|
|
107
|
+
fd = openSync(this.path(name), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (systemCode(error) === "ENOENT")
|
|
111
|
+
return null;
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const stat = fstatSync(fd);
|
|
116
|
+
if (!stat.isFile() ||
|
|
117
|
+
stat.uid !== process.getuid?.() ||
|
|
118
|
+
stat.mode & 0o077 ||
|
|
119
|
+
stat.nlink !== 1 ||
|
|
120
|
+
stat.size > MAX_PRIVATE_BYTES)
|
|
121
|
+
throw new ManagedLocalStateError("managed_private_file_invalid");
|
|
122
|
+
// A file can grow after fstat. Bound the allocation and every read as well.
|
|
123
|
+
const bytes = Buffer.alloc(MAX_PRIVATE_BYTES + 1);
|
|
124
|
+
let size = 0;
|
|
125
|
+
while (size < bytes.length) {
|
|
126
|
+
const count = readSync(fd, bytes, size, bytes.length - size, null);
|
|
127
|
+
if (count === 0)
|
|
128
|
+
break;
|
|
129
|
+
size += count;
|
|
130
|
+
}
|
|
131
|
+
if (size > MAX_PRIVATE_BYTES)
|
|
132
|
+
throw new ManagedLocalStateError("managed_private_file_invalid");
|
|
133
|
+
return JSON.parse(bytes.toString("utf8", 0, size));
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
closeSync(fd);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
write(name, value, exclusive = false) {
|
|
141
|
+
return guard(() => {
|
|
142
|
+
const path = this.path(name);
|
|
143
|
+
const body = JSON.stringify(value) + "\n";
|
|
144
|
+
if (Buffer.byteLength(body) > MAX_PRIVATE_BYTES)
|
|
145
|
+
throw new ManagedLocalStateError("managed_private_file_invalid");
|
|
146
|
+
// Validate an existing destination instead of overwriting an unknown / linked file.
|
|
147
|
+
if (this.read(name) !== null && exclusive)
|
|
148
|
+
return false;
|
|
149
|
+
const temp = join(this.root, `.write-${randomBytes(16).toString("hex")}`);
|
|
150
|
+
try {
|
|
151
|
+
const fd = openSync(temp, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
152
|
+
try {
|
|
153
|
+
writeFileSync(fd, body);
|
|
154
|
+
fsyncSync(fd);
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
closeSync(fd);
|
|
158
|
+
}
|
|
159
|
+
this.checkRoot();
|
|
160
|
+
if (exclusive) {
|
|
161
|
+
try {
|
|
162
|
+
linkSync(temp, path);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
if (systemCode(error) === "EEXIST")
|
|
166
|
+
return false;
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
renameSync(temp, path);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
unlinkIfPresent(temp);
|
|
176
|
+
this.syncDirectory();
|
|
177
|
+
}
|
|
178
|
+
return true;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
// SQLite is only an OS-released cross-process mutex here: no schema, metadata or
|
|
182
|
+
// secrets are stored in it. Crash recovery never unlinks another process's lock.
|
|
183
|
+
// This callback is intentionally synchronous: never hold it across network I/O.
|
|
184
|
+
transaction(run) {
|
|
185
|
+
return guard(() => {
|
|
186
|
+
this.checkRoot();
|
|
187
|
+
const path = join(this.root, "serialization.sqlite");
|
|
188
|
+
try {
|
|
189
|
+
const fd = openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
190
|
+
closeSync(fd);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
if (systemCode(error) !== "EEXIST")
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
const stat = lstatSync(path);
|
|
197
|
+
if (!stat.isFile() ||
|
|
198
|
+
stat.isSymbolicLink() ||
|
|
199
|
+
stat.uid !== process.getuid?.() ||
|
|
200
|
+
stat.mode & 0o077 ||
|
|
201
|
+
stat.nlink !== 1)
|
|
202
|
+
throw new ManagedLocalStateError("managed_private_file_invalid");
|
|
203
|
+
const lock = new Database(path, { timeout: 1000 });
|
|
204
|
+
try {
|
|
205
|
+
lock.exec("BEGIN IMMEDIATE");
|
|
206
|
+
const result = run();
|
|
207
|
+
if (result && typeof result === "object" && "then" in result)
|
|
208
|
+
throw new ManagedLocalStateError("managed_transaction_must_be_synchronous");
|
|
209
|
+
lock.exec("COMMIT");
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (systemCode(error) === "SQLITE_BUSY")
|
|
214
|
+
throw new ManagedLocalStateError("managed_state_busy");
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
lock.close();
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// Separate per-model-session execution lease. Unlike the short journal mutex,
|
|
223
|
+
// this lock deliberately spans one bounded model invocation. It stores no data,
|
|
224
|
+
// fails immediately on contention, and is released by the OS if the Host dies.
|
|
225
|
+
acquireExecutionLease(name) {
|
|
226
|
+
return guard(() => {
|
|
227
|
+
if (!/^(model|workspace)-[a-f0-9]{64}$/.test(name))
|
|
228
|
+
throw new ManagedLocalStateError("managed_record_name_invalid");
|
|
229
|
+
this.checkRoot();
|
|
230
|
+
const path = join(this.root, `${name}.sqlite`);
|
|
231
|
+
try {
|
|
232
|
+
const fd = openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
233
|
+
closeSync(fd);
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
if (systemCode(error) !== "EEXIST")
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
const stat = lstatSync(path);
|
|
240
|
+
if (!stat.isFile() ||
|
|
241
|
+
stat.isSymbolicLink() ||
|
|
242
|
+
stat.uid !== process.getuid?.() ||
|
|
243
|
+
stat.mode & 0o077 ||
|
|
244
|
+
stat.nlink !== 1)
|
|
245
|
+
throw new ManagedLocalStateError("managed_private_file_invalid");
|
|
246
|
+
const lock = new Database(path, { timeout: 0 });
|
|
247
|
+
try {
|
|
248
|
+
lock.exec("BEGIN IMMEDIATE");
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
lock.close();
|
|
252
|
+
if (systemCode(error) === "SQLITE_BUSY")
|
|
253
|
+
throw new ManagedLocalStateError(name.startsWith("workspace-") ? "managed_workspace_busy" : "managed_session_busy");
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
let released = false;
|
|
257
|
+
return () => {
|
|
258
|
+
if (!released) {
|
|
259
|
+
released = true;
|
|
260
|
+
lock.close();
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
syncDirectory() {
|
|
266
|
+
const fd = openSync(this.root, constants.O_RDONLY);
|
|
267
|
+
try {
|
|
268
|
+
fsyncSync(fd);
|
|
269
|
+
}
|
|
270
|
+
finally {
|
|
271
|
+
closeSync(fd);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=private-store.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ProjectId } from "@tutti/shared/ids";
|
|
2
|
+
import type { ProviderConfigProjection } from "@tutti/shared/schemas/api";
|
|
3
|
+
import { NativeManagedRuntime, type ManagedRuntimeObservation } from "./runtime.js";
|
|
4
|
+
export declare function readProjectModelAccess(options: {
|
|
5
|
+
tuttiHome: string;
|
|
6
|
+
relayUrl: string;
|
|
7
|
+
projectId: ProjectId;
|
|
8
|
+
}): ProviderConfigProjection;
|
|
9
|
+
export declare function hasProjectModelConfiguration(projection: ProviderConfigProjection): boolean;
|
|
10
|
+
export declare function createNativeManagedHostRuntime(options: {
|
|
11
|
+
tuttiHome: string;
|
|
12
|
+
relayUrl: string;
|
|
13
|
+
projectId: ProjectId;
|
|
14
|
+
workspaceRoot: string;
|
|
15
|
+
surface: "standalone" | "feishu";
|
|
16
|
+
observe?: (event: ManagedRuntimeObservation) => void;
|
|
17
|
+
}): NativeManagedRuntime | null;
|
|
18
|
+
//# sourceMappingURL=project-provider.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import { readOpenAiProviderConfigProjection } from "../../providers/openai/provider-config.js";
|
|
3
|
+
import { findNativeManagedProject } from "./state.js";
|
|
4
|
+
import { readHostRegistrationSecret } from "../cli/machine-local.js";
|
|
5
|
+
import { ManagedLocalStateError } from "./private-store.js";
|
|
6
|
+
import { NativeManagedRuntime } from "./runtime.js";
|
|
7
|
+
// A mode projection, not a promise that current remote authority or quota is
|
|
8
|
+
// available. Every actual managed invocation independently verifies both.
|
|
9
|
+
export function readProjectModelAccess(options) {
|
|
10
|
+
const native = findNativeManagedProject(options);
|
|
11
|
+
if (native !== null) {
|
|
12
|
+
return { status: "managed", funding_kind: "trial" };
|
|
13
|
+
}
|
|
14
|
+
return readOpenAiProviderConfigProjection(options);
|
|
15
|
+
}
|
|
16
|
+
export function hasProjectModelConfiguration(projection) {
|
|
17
|
+
return projection.status === "configured" || projection.status === "managed";
|
|
18
|
+
}
|
|
19
|
+
export function createNativeManagedHostRuntime(options) {
|
|
20
|
+
const managed = findNativeManagedProject(options);
|
|
21
|
+
if (managed === null)
|
|
22
|
+
return null;
|
|
23
|
+
if (managed.journal.workspace_root !== realpathSync(options.workspaceRoot) ||
|
|
24
|
+
managed.journal.surface !== options.surface ||
|
|
25
|
+
managed.journal.host_registration_secret !==
|
|
26
|
+
readHostRegistrationSecret(options.tuttiHome, options.projectId).secret)
|
|
27
|
+
throw new ManagedLocalStateError("managed_registration_mismatch");
|
|
28
|
+
return new NativeManagedRuntime(options);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=project-provider.js.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { type Static } from "@sinclair/typebox";
|
|
2
|
+
import type { ProjectId } from "@tutti/shared/ids";
|
|
3
|
+
export declare const InstallationSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
+
version: import("@sinclair/typebox").TLiteral<1>;
|
|
5
|
+
relay_origin: import("@sinclair/typebox").TString;
|
|
6
|
+
installation_ref: import("@sinclair/typebox").TString;
|
|
7
|
+
secret: import("@sinclair/typebox").TString;
|
|
8
|
+
created_at: import("@sinclair/typebox").TString;
|
|
9
|
+
}>;
|
|
10
|
+
export type Installation = Static<typeof InstallationSchema>;
|
|
11
|
+
export declare const CreationJournalSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
12
|
+
state: import("@sinclair/typebox").TLiteral<"awaiting_authorization">;
|
|
13
|
+
version: import("@sinclair/typebox").TLiteral<2>;
|
|
14
|
+
request_ref: import("@sinclair/typebox").TString;
|
|
15
|
+
project_id: import("@sinclair/typebox").TString;
|
|
16
|
+
relay_origin: import("@sinclair/typebox").TString;
|
|
17
|
+
installation_ref: import("@sinclair/typebox").TString;
|
|
18
|
+
workspace_root: import("@sinclair/typebox").TString;
|
|
19
|
+
display_name: import("@sinclair/typebox").TString;
|
|
20
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
21
|
+
surface: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"standalone">, import("@sinclair/typebox").TLiteral<"feishu">]>;
|
|
22
|
+
existing_relay_project_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
23
|
+
previous_request_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
24
|
+
handoff_token: import("@sinclair/typebox").TString;
|
|
25
|
+
host_registration_secret: import("@sinclair/typebox").TString;
|
|
26
|
+
created_at: import("@sinclair/typebox").TString;
|
|
27
|
+
expires_at: import("@sinclair/typebox").TString;
|
|
28
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
29
|
+
state: import("@sinclair/typebox").TLiteral<"prepared">;
|
|
30
|
+
creation_ref: import("@sinclair/typebox").TString;
|
|
31
|
+
version: import("@sinclair/typebox").TLiteral<2>;
|
|
32
|
+
request_ref: import("@sinclair/typebox").TString;
|
|
33
|
+
project_id: import("@sinclair/typebox").TString;
|
|
34
|
+
relay_origin: import("@sinclair/typebox").TString;
|
|
35
|
+
installation_ref: import("@sinclair/typebox").TString;
|
|
36
|
+
workspace_root: import("@sinclair/typebox").TString;
|
|
37
|
+
display_name: import("@sinclair/typebox").TString;
|
|
38
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
39
|
+
surface: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"standalone">, import("@sinclair/typebox").TLiteral<"feishu">]>;
|
|
40
|
+
existing_relay_project_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
41
|
+
previous_request_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
42
|
+
handoff_token: import("@sinclair/typebox").TString;
|
|
43
|
+
host_registration_secret: import("@sinclair/typebox").TString;
|
|
44
|
+
created_at: import("@sinclair/typebox").TString;
|
|
45
|
+
expires_at: import("@sinclair/typebox").TString;
|
|
46
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
47
|
+
state: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"validated">, import("@sinclair/typebox").TLiteral<"validation_unknown">, import("@sinclair/typebox").TLiteral<"validation_failed">]>;
|
|
48
|
+
creation_ref: import("@sinclair/typebox").TString;
|
|
49
|
+
version: import("@sinclair/typebox").TLiteral<2>;
|
|
50
|
+
request_ref: import("@sinclair/typebox").TString;
|
|
51
|
+
project_id: import("@sinclair/typebox").TString;
|
|
52
|
+
relay_origin: import("@sinclair/typebox").TString;
|
|
53
|
+
installation_ref: import("@sinclair/typebox").TString;
|
|
54
|
+
workspace_root: import("@sinclair/typebox").TString;
|
|
55
|
+
display_name: import("@sinclair/typebox").TString;
|
|
56
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
57
|
+
surface: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"standalone">, import("@sinclair/typebox").TLiteral<"feishu">]>;
|
|
58
|
+
existing_relay_project_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
59
|
+
previous_request_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
60
|
+
handoff_token: import("@sinclair/typebox").TString;
|
|
61
|
+
host_registration_secret: import("@sinclair/typebox").TString;
|
|
62
|
+
created_at: import("@sinclair/typebox").TString;
|
|
63
|
+
expires_at: import("@sinclair/typebox").TString;
|
|
64
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
65
|
+
state: import("@sinclair/typebox").TLiteral<"registered">;
|
|
66
|
+
creation_ref: import("@sinclair/typebox").TString;
|
|
67
|
+
authority: import("@sinclair/typebox").TObject<{
|
|
68
|
+
delegation_ref: import("@sinclair/typebox").TString;
|
|
69
|
+
grant_ref: import("@sinclair/typebox").TString;
|
|
70
|
+
relay_project_ref: import("@sinclair/typebox").TString;
|
|
71
|
+
installation_ref: import("@sinclair/typebox").TString;
|
|
72
|
+
funding_kind: import("@sinclair/typebox").TLiteral<"trial">;
|
|
73
|
+
expires_at: import("@sinclair/typebox").TNull;
|
|
74
|
+
state: import("@sinclair/typebox").TLiteral<"active">;
|
|
75
|
+
model_access: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"runtime_authority_required">, import("@sinclair/typebox").TLiteral<"not_enabled">]>;
|
|
76
|
+
}>;
|
|
77
|
+
version: import("@sinclair/typebox").TLiteral<2>;
|
|
78
|
+
request_ref: import("@sinclair/typebox").TString;
|
|
79
|
+
project_id: import("@sinclair/typebox").TString;
|
|
80
|
+
relay_origin: import("@sinclair/typebox").TString;
|
|
81
|
+
installation_ref: import("@sinclair/typebox").TString;
|
|
82
|
+
workspace_root: import("@sinclair/typebox").TString;
|
|
83
|
+
display_name: import("@sinclair/typebox").TString;
|
|
84
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
85
|
+
surface: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"standalone">, import("@sinclair/typebox").TLiteral<"feishu">]>;
|
|
86
|
+
existing_relay_project_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
87
|
+
previous_request_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
88
|
+
handoff_token: import("@sinclair/typebox").TString;
|
|
89
|
+
host_registration_secret: import("@sinclair/typebox").TString;
|
|
90
|
+
created_at: import("@sinclair/typebox").TString;
|
|
91
|
+
expires_at: import("@sinclair/typebox").TString;
|
|
92
|
+
}>]>;
|
|
93
|
+
export type CreationJournal = Static<typeof CreationJournalSchema> & {
|
|
94
|
+
project_id: ProjectId;
|
|
95
|
+
};
|
|
96
|
+
export declare const NativeProjectPointerSchema: import("@sinclair/typebox").TObject<{
|
|
97
|
+
version: import("@sinclair/typebox").TLiteral<1>;
|
|
98
|
+
project_id: import("@sinclair/typebox").TString;
|
|
99
|
+
request_ref: import("@sinclair/typebox").TString;
|
|
100
|
+
}>;
|
|
101
|
+
export declare function parseInstallation(raw: unknown, origin: string): Installation;
|
|
102
|
+
export declare function parseJournal(raw: unknown, origin: string, requestRef: string): CreationJournal;
|
|
103
|
+
//# sourceMappingURL=records.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { Value } from "@sinclair/typebox/value";
|
|
3
|
+
import { IdempotencyKeySchema, ProjectIdSchema, RelayProjectRefSchema, } from "@tutti/shared/schemas/domain";
|
|
4
|
+
import { AuthoritySecretSchema, AuthorityTimestampSchema, isAuthorityTimestamp, HostInstallationRefSchema, HostDelegationProjectionSchema, ManagedCreationRefSchema, } from "@tutti/shared/schemas/internal";
|
|
5
|
+
import { ManagedLocalStateError } from "./private-store.js";
|
|
6
|
+
import { upgradeTieredPrivateRecord } from "./legacy-records.js";
|
|
7
|
+
export const InstallationSchema = Type.Object({
|
|
8
|
+
version: Type.Literal(1),
|
|
9
|
+
relay_origin: Type.String({ maxLength: 500 }),
|
|
10
|
+
installation_ref: HostInstallationRefSchema,
|
|
11
|
+
secret: AuthoritySecretSchema,
|
|
12
|
+
created_at: AuthorityTimestampSchema,
|
|
13
|
+
}, { additionalProperties: false });
|
|
14
|
+
const DraftFields = {
|
|
15
|
+
version: Type.Literal(2),
|
|
16
|
+
request_ref: IdempotencyKeySchema,
|
|
17
|
+
project_id: ProjectIdSchema,
|
|
18
|
+
relay_origin: Type.String({ maxLength: 500 }),
|
|
19
|
+
installation_ref: HostInstallationRefSchema,
|
|
20
|
+
workspace_root: Type.String({ minLength: 1, maxLength: 4096 }),
|
|
21
|
+
display_name: Type.String({ minLength: 1, maxLength: 80 }),
|
|
22
|
+
description: Type.Optional(Type.String({ maxLength: 160 })),
|
|
23
|
+
surface: Type.Union([Type.Literal("standalone"), Type.Literal("feishu")]),
|
|
24
|
+
existing_relay_project_ref: Type.Optional(RelayProjectRefSchema),
|
|
25
|
+
previous_request_ref: Type.Optional(IdempotencyKeySchema),
|
|
26
|
+
handoff_token: AuthoritySecretSchema,
|
|
27
|
+
host_registration_secret: AuthoritySecretSchema,
|
|
28
|
+
created_at: AuthorityTimestampSchema,
|
|
29
|
+
expires_at: AuthorityTimestampSchema,
|
|
30
|
+
};
|
|
31
|
+
export const CreationJournalSchema = Type.Union([
|
|
32
|
+
Type.Object({ ...DraftFields, state: Type.Literal("awaiting_authorization") }, { additionalProperties: false }),
|
|
33
|
+
Type.Object({ ...DraftFields, state: Type.Literal("prepared"), creation_ref: ManagedCreationRefSchema }, { additionalProperties: false }),
|
|
34
|
+
Type.Object({
|
|
35
|
+
...DraftFields,
|
|
36
|
+
state: Type.Union([
|
|
37
|
+
Type.Literal("validated"),
|
|
38
|
+
Type.Literal("validation_unknown"),
|
|
39
|
+
Type.Literal("validation_failed"),
|
|
40
|
+
]),
|
|
41
|
+
creation_ref: ManagedCreationRefSchema,
|
|
42
|
+
}, { additionalProperties: false }),
|
|
43
|
+
Type.Object({
|
|
44
|
+
...DraftFields,
|
|
45
|
+
state: Type.Literal("registered"),
|
|
46
|
+
creation_ref: ManagedCreationRefSchema,
|
|
47
|
+
authority: HostDelegationProjectionSchema,
|
|
48
|
+
}, { additionalProperties: false }),
|
|
49
|
+
]);
|
|
50
|
+
export const NativeProjectPointerSchema = Type.Object({
|
|
51
|
+
version: Type.Literal(1),
|
|
52
|
+
project_id: ProjectIdSchema,
|
|
53
|
+
request_ref: IdempotencyKeySchema,
|
|
54
|
+
}, { additionalProperties: false });
|
|
55
|
+
export function parseInstallation(raw, origin) {
|
|
56
|
+
if (!Value.Check(InstallationSchema, raw) ||
|
|
57
|
+
raw.relay_origin !== origin ||
|
|
58
|
+
!isAuthorityTimestamp(raw.created_at))
|
|
59
|
+
throw new ManagedLocalStateError("managed_installation_invalid");
|
|
60
|
+
return raw;
|
|
61
|
+
}
|
|
62
|
+
export function parseJournal(raw, origin, requestRef) {
|
|
63
|
+
raw = upgradeTieredPrivateRecord(raw, true);
|
|
64
|
+
if (!Value.Check(CreationJournalSchema, raw) ||
|
|
65
|
+
raw.relay_origin !== origin ||
|
|
66
|
+
raw.request_ref !== requestRef ||
|
|
67
|
+
!isAuthorityTimestamp(raw.created_at) ||
|
|
68
|
+
!isAuthorityTimestamp(raw.expires_at) ||
|
|
69
|
+
raw.expires_at <= raw.created_at)
|
|
70
|
+
throw new ManagedLocalStateError("managed_journal_invalid");
|
|
71
|
+
// ProjectIdSchema checked the complete branded ID pattern above.
|
|
72
|
+
return raw;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReadOnlyChatAssistantModel } from "../../chat-assistant/index.js";
|
|
2
|
+
import type { RunPipelineRunner } from "../../control-plane/index.js";
|
|
3
|
+
import { type ProjectOpenAiProcedureWorkflowRunnerOptions } from "../../control-plane/workflows/openai.js";
|
|
4
|
+
import type { ProcedureWorkflowRunner } from "../../control-plane/workflows/types.js";
|
|
5
|
+
import { type ProjectOpenAiReadOnlyChatAssistantModelOptions } from "../../providers/openai/chat-assistant.js";
|
|
6
|
+
import { type ProjectOpenAiRunPipelineRunnerOptions } from "../../run-pipeline/openai.js";
|
|
7
|
+
import { type ManagedExecutionRuntime } from "./execution-binding.js";
|
|
8
|
+
export declare function createManagedWorkflowRunner(runtime: ManagedExecutionRuntime, options: ProjectOpenAiProcedureWorkflowRunnerOptions): ProcedureWorkflowRunner;
|
|
9
|
+
export declare function createManagedRunPipeline(runtime: ManagedExecutionRuntime, options: ProjectOpenAiRunPipelineRunnerOptions): RunPipelineRunner;
|
|
10
|
+
export declare function createManagedChatModel(runtime: ManagedExecutionRuntime, options: ProjectOpenAiReadOnlyChatAssistantModelOptions): ReadOnlyChatAssistantModel;
|
|
11
|
+
//# sourceMappingURL=runners.d.ts.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { createOpenAiProcedureWorkflowRunner, } from "../../control-plane/workflows/openai.js";
|
|
3
|
+
import { createOpenAiReadOnlyChatAssistantModel, } from "../../providers/openai/chat-assistant.js";
|
|
4
|
+
import { createOpenAiStructuredOutputClient } from "../../providers/openai/sdk-procedure-runner.js";
|
|
5
|
+
import { inspectCodexLinuxSandboxReadiness } from "../../providers/openai/app-server/linux-sandbox-readiness.js";
|
|
6
|
+
import { createOpenAiRunPipelineRunner, } from "../../run-pipeline/openai.js";
|
|
7
|
+
import { getProjectUserSkillsRoot } from "../../skills/index.js";
|
|
8
|
+
import { bindManagedExecution } from "./execution-binding.js";
|
|
9
|
+
import { failedBeforeChecks } from "../../run-pipeline/result-projections.js";
|
|
10
|
+
import { ManagedLocalStateError } from "./private-store.js";
|
|
11
|
+
import { ManagedControlError } from "./model-control-client.js";
|
|
12
|
+
import { NativeAuthorityTransportError } from "@tutti/relay-client";
|
|
13
|
+
// Shell composition only. The provider adapters know nothing about account,
|
|
14
|
+
// delegation, New API, or private native journals.
|
|
15
|
+
export function createManagedWorkflowRunner(runtime, options) {
|
|
16
|
+
async function resolve(ref) {
|
|
17
|
+
const access = await bindManagedExecution(runtime, { kind: "workflow", ref });
|
|
18
|
+
return createOpenAiProcedureWorkflowRunner({
|
|
19
|
+
config: access.config,
|
|
20
|
+
client: createOpenAiStructuredOutputClient({
|
|
21
|
+
credentialLease: access.credentialLease,
|
|
22
|
+
apiBaseUrl: access.config.api_base_url,
|
|
23
|
+
}),
|
|
24
|
+
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
25
|
+
...(options.recordUsage === undefined ? {} : { recordUsage: options.recordUsage }),
|
|
26
|
+
readOnlyAppServer: {
|
|
27
|
+
...options,
|
|
28
|
+
credentialLease: access.credentialLease,
|
|
29
|
+
userSkillsRoot: getProjectUserSkillsRoot(options.tuttiHome, options.projectId),
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
async runScratchpadRefresh(input, context) {
|
|
35
|
+
return (await resolve(context.workflow_ref)).runScratchpadRefresh(input, context);
|
|
36
|
+
},
|
|
37
|
+
async runTaskCompile(input, context) {
|
|
38
|
+
return (await resolve(input.workflow_ref)).runTaskCompile(input, context);
|
|
39
|
+
},
|
|
40
|
+
async runProjectContextBootstrap(input, context) {
|
|
41
|
+
const runner = await resolve(context?.workflow_ref ?? randomUUID());
|
|
42
|
+
return runner.runProjectContextBootstrap(input, context);
|
|
43
|
+
},
|
|
44
|
+
async runContextSync(input, context) {
|
|
45
|
+
return (await resolve(input.workflow_ref)).runContextSync(input, context);
|
|
46
|
+
},
|
|
47
|
+
async runReferenceFileSummary(input, context) {
|
|
48
|
+
// One workflow drains multiple targets concurrently. Do not make two files
|
|
49
|
+
// share a model-session lease, or expose filesystem paths as owner refs.
|
|
50
|
+
const ref = createHash("sha256")
|
|
51
|
+
.update(JSON.stringify([input.workflow_ref, input.file.path, input.file.blob_oid]))
|
|
52
|
+
.digest("hex");
|
|
53
|
+
return (await resolve(ref)).runReferenceFileSummary(input, context);
|
|
54
|
+
},
|
|
55
|
+
async runProjectBriefRefresh(input, context) {
|
|
56
|
+
return (await resolve(context?.workflow_ref ?? randomUUID())).runProjectBriefRefresh(input, context);
|
|
57
|
+
},
|
|
58
|
+
async runFollowUpCheck(input, context) {
|
|
59
|
+
return (await resolve(input.workflow_ref)).runFollowUpCheck(input, context);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function createManagedRunPipeline(runtime, options) {
|
|
64
|
+
return {
|
|
65
|
+
async runTask(input) {
|
|
66
|
+
let access;
|
|
67
|
+
try {
|
|
68
|
+
access = await bindManagedExecution(runtime, { kind: "task", ref: input.task.id });
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const known = error instanceof ManagedLocalStateError ||
|
|
72
|
+
error instanceof ManagedControlError ||
|
|
73
|
+
error instanceof NativeAuthorityTransportError;
|
|
74
|
+
return failedBeforeChecks({
|
|
75
|
+
summary: "Tutti trial access is unavailable. Check project authorization and trial allowance before retrying.",
|
|
76
|
+
errorCode: known ? error.code : "managed_selection_unavailable",
|
|
77
|
+
retryable: true,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return createOpenAiRunPipelineRunner({
|
|
81
|
+
...options,
|
|
82
|
+
...access,
|
|
83
|
+
userSkillsRoot: getProjectUserSkillsRoot(options.tuttiHome, options.projectId),
|
|
84
|
+
...(process.platform === "linux"
|
|
85
|
+
? { codexSandboxReadiness: () => inspectCodexLinuxSandboxReadiness() }
|
|
86
|
+
: {}),
|
|
87
|
+
}).runTask(input);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function createManagedChatModel(runtime, options) {
|
|
92
|
+
return {
|
|
93
|
+
async answer(input) {
|
|
94
|
+
const access = await bindManagedExecution(runtime, { kind: "chat", ref: randomUUID() });
|
|
95
|
+
return createOpenAiReadOnlyChatAssistantModel({
|
|
96
|
+
...options,
|
|
97
|
+
...access,
|
|
98
|
+
userSkillsRoot: getProjectUserSkillsRoot(options.tuttiHome, options.projectId),
|
|
99
|
+
}).answer(input);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=runners.js.map
|