@kitman-sh/cli 0.10.74 → 0.10.76
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/{chunk-kd02wvfa.js → chunk-0e3t90fs.js} +8 -8
- package/dist/{chunk-x0ep0a1y.js → chunk-1zt1yeme.js} +4 -4
- package/dist/{chunk-5rs3yv84.js → chunk-225qhz3b.js} +15 -15
- package/dist/{chunk-ggax0n15.js → chunk-3teaa3qx.js} +3 -3
- package/dist/{chunk-rrnee9mk.js → chunk-545b129z.js} +38 -5
- package/dist/{chunk-q3c7vmby.js → chunk-76ctrqm6.js} +1 -1
- package/dist/{chunk-rt94p780.js → chunk-89547s8p.js} +647 -75
- package/dist/{chunk-1rry0tsn.js → chunk-98sg1yyd.js} +2 -2
- package/dist/{chunk-60333x3q.js → chunk-9zd52pda.js} +5 -5
- package/dist/{chunk-3edjgnxf.js → chunk-b0cscqbw.js} +25 -3
- package/dist/{chunk-g4fvd8r1.js → chunk-bcbne0ek.js} +22 -6
- package/dist/{chunk-8bhea26e.js → chunk-e3dmkypq.js} +5 -5
- package/dist/{chunk-csbf77zs.js → chunk-e8zm8z3a.js} +4 -4
- package/dist/{chunk-3ne401fy.js → chunk-f0stxany.js} +7 -7
- package/dist/{chunk-rm83dbpv.js → chunk-fq47a5yd.js} +2 -2
- package/dist/{chunk-2v7pbpfw.js → chunk-fqhxxxmp.js} +3 -3
- package/dist/{chunk-mzphfkyk.js → chunk-h3y4z2c0.js} +7 -7
- package/dist/{chunk-yzm5s3ng.js → chunk-jb01khjp.js} +4 -4
- package/dist/{chunk-d3ksv8y1.js → chunk-jbwk6k6m.js} +44 -7
- package/dist/{chunk-xz1z7j2d.js → chunk-p8g8qyev.js} +4 -4
- package/dist/{chunk-gmnqchsc.js → chunk-t07tn0ay.js} +4 -4
- package/dist/{chunk-v01c0k6j.js → chunk-tzz4fv17.js} +1 -1
- package/dist/{chunk-dk0ftqwg.js → chunk-xb70ys3n.js} +1 -1
- package/dist/{chunk-mv288r6q.js → chunk-z7p5y767.js} +17 -17
- package/dist/index.js +4 -4
- package/package.json +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
toJsonValue,
|
|
4
|
+
isKeyOf,
|
|
4
5
|
isNumber,
|
|
5
6
|
isObject,
|
|
6
7
|
isJsonObject,
|
|
7
8
|
isString
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-tzz4fv17.js";
|
|
9
10
|
import {
|
|
10
11
|
pipeArguments,
|
|
11
12
|
dual,
|
|
@@ -19,7 +20,10 @@ import {
|
|
|
19
20
|
match,
|
|
20
21
|
getOrElse,
|
|
21
22
|
getOrUndefined,
|
|
23
|
+
liftThrowable,
|
|
22
24
|
flatMap,
|
|
25
|
+
toArray,
|
|
26
|
+
filter2,
|
|
23
27
|
Service2,
|
|
24
28
|
Reference,
|
|
25
29
|
fromInputUnsafe,
|
|
@@ -50,6 +54,7 @@ import {
|
|
|
50
54
|
doneUnsafe,
|
|
51
55
|
makeUnsafe6,
|
|
52
56
|
provide,
|
|
57
|
+
succeed5,
|
|
53
58
|
effect,
|
|
54
59
|
mergeAll,
|
|
55
60
|
die2,
|
|
@@ -104,7 +109,7 @@ import {
|
|
|
104
109
|
sleep,
|
|
105
110
|
raceAllFirst,
|
|
106
111
|
raceFirst,
|
|
107
|
-
|
|
112
|
+
filter3,
|
|
108
113
|
matchEffect2,
|
|
109
114
|
context,
|
|
110
115
|
provide3,
|
|
@@ -136,31 +141,36 @@ import {
|
|
|
136
141
|
String4,
|
|
137
142
|
Boolean2,
|
|
138
143
|
Struct,
|
|
144
|
+
Record,
|
|
139
145
|
ArraySchema,
|
|
140
146
|
Union,
|
|
141
147
|
Literals,
|
|
142
148
|
NullOr,
|
|
143
149
|
isPattern,
|
|
144
150
|
Finite,
|
|
151
|
+
isGreaterThan,
|
|
145
152
|
isGreaterThanOrEqualTo,
|
|
146
153
|
isLessThanOrEqualTo,
|
|
147
154
|
Int,
|
|
148
155
|
isMinLength,
|
|
149
156
|
isMaxLength,
|
|
157
|
+
NonEmptyString,
|
|
150
158
|
Date2,
|
|
151
159
|
fromJsonString,
|
|
152
160
|
TaggedError2,
|
|
161
|
+
Json,
|
|
153
162
|
decodeJsonString,
|
|
154
163
|
decodeJsonStringOption,
|
|
155
164
|
encodeJsonStringSync,
|
|
156
165
|
encodePrettyJsonString,
|
|
157
166
|
decodeJsonStringSync,
|
|
158
167
|
encodeUnknownJsonStringSync
|
|
159
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-jbwk6k6m.js";
|
|
160
169
|
import {
|
|
161
170
|
Id,
|
|
162
|
-
secretReference
|
|
163
|
-
|
|
171
|
+
secretReference,
|
|
172
|
+
secretPlaceholder
|
|
173
|
+
} from "./chunk-545b129z.js";
|
|
164
174
|
import {
|
|
165
175
|
currentTimeMillis,
|
|
166
176
|
SecureRandom,
|
|
@@ -190,9 +200,15 @@ import {
|
|
|
190
200
|
digestSha256,
|
|
191
201
|
AgentEvent,
|
|
192
202
|
get,
|
|
203
|
+
post,
|
|
193
204
|
setHeaders,
|
|
205
|
+
acceptJson,
|
|
206
|
+
bodyJsonUnsafe,
|
|
207
|
+
bodyUrlParams,
|
|
208
|
+
schemaBodyJson,
|
|
194
209
|
filterStatusOk,
|
|
195
210
|
HttpClient,
|
|
211
|
+
layer4,
|
|
196
212
|
SetupArchive,
|
|
197
213
|
kitMcpSecretNames,
|
|
198
214
|
RunSettled,
|
|
@@ -227,7 +243,7 @@ import {
|
|
|
227
243
|
installCommand,
|
|
228
244
|
checkServicesFile,
|
|
229
245
|
checkServices
|
|
230
|
-
} from "./chunk-
|
|
246
|
+
} from "./chunk-bcbne0ek.js";
|
|
231
247
|
import {
|
|
232
248
|
join,
|
|
233
249
|
interrupt,
|
|
@@ -267,7 +283,7 @@ import {
|
|
|
267
283
|
writeSrtSettings2,
|
|
268
284
|
srtStepArgv2,
|
|
269
285
|
srtArgv2
|
|
270
|
-
} from "./chunk-
|
|
286
|
+
} from "./chunk-xb70ys3n.js";
|
|
271
287
|
import {
|
|
272
288
|
writeAgentEnvironmentConfigFile2,
|
|
273
289
|
readManifestSkillPaths2,
|
|
@@ -283,8 +299,8 @@ import {
|
|
|
283
299
|
applyAgentEnvironmentMaterialization2,
|
|
284
300
|
isPathWithin2,
|
|
285
301
|
skillIdentity2
|
|
286
|
-
} from "./chunk-
|
|
287
|
-
import"./chunk-
|
|
302
|
+
} from "./chunk-e3dmkypq.js";
|
|
303
|
+
import"./chunk-fqhxxxmp.js";
|
|
288
304
|
import {
|
|
289
305
|
egressAllowed,
|
|
290
306
|
writeSecretRegistry,
|
|
@@ -294,7 +310,7 @@ import {
|
|
|
294
310
|
secretFilter2,
|
|
295
311
|
opaqueTunnelRefusal2,
|
|
296
312
|
isOpaqueConnectReason2
|
|
297
|
-
} from "./chunk-
|
|
313
|
+
} from "./chunk-b0cscqbw.js";
|
|
298
314
|
import {
|
|
299
315
|
sliceBytes2,
|
|
300
316
|
maxLineBytes2,
|
|
@@ -302,23 +318,23 @@ import {
|
|
|
302
318
|
decodedOption2,
|
|
303
319
|
decoded2,
|
|
304
320
|
readOpencode2
|
|
305
|
-
} from "./chunk-
|
|
321
|
+
} from "./chunk-e8zm8z3a.js";
|
|
306
322
|
import {
|
|
307
323
|
uploadRunFile,
|
|
308
324
|
programLease,
|
|
309
325
|
rpcRunFiles,
|
|
310
326
|
programHostsEnv,
|
|
311
327
|
undeclaredHostsEnv
|
|
312
|
-
} from "./chunk-
|
|
313
|
-
import"./chunk-
|
|
328
|
+
} from "./chunk-jb01khjp.js";
|
|
329
|
+
import"./chunk-p8g8qyev.js";
|
|
314
330
|
import {
|
|
315
331
|
nextInt
|
|
316
|
-
} from "./chunk-
|
|
332
|
+
} from "./chunk-76ctrqm6.js";
|
|
317
333
|
import {
|
|
318
334
|
ChildProcessSpawner,
|
|
319
335
|
make3
|
|
320
|
-
} from "./chunk-
|
|
321
|
-
import"./chunk-
|
|
336
|
+
} from "./chunk-98sg1yyd.js";
|
|
337
|
+
import"./chunk-3teaa3qx.js";
|
|
322
338
|
|
|
323
339
|
// packages/core/src/sync-kit.ts
|
|
324
340
|
import { createHash } from "crypto";
|
|
@@ -1614,6 +1630,8 @@ function repositoryUrl(repoBinding) {
|
|
|
1614
1630
|
}
|
|
1615
1631
|
// packages/agent-runtime/src/harness-adapters.ts
|
|
1616
1632
|
import { homedir } from "os";
|
|
1633
|
+
var anthropicHosts = ["api.anthropic.com", "console.anthropic.com", "claude.ai"];
|
|
1634
|
+
var githubCopilotHosts = ["api.githubcopilot.com", "*.githubcopilot.com"];
|
|
1617
1635
|
var HarnessAdapters = [
|
|
1618
1636
|
{
|
|
1619
1637
|
id: "claude",
|
|
@@ -1628,10 +1646,20 @@ var HarnessAdapters = [
|
|
|
1628
1646
|
file: ".credentials.json",
|
|
1629
1647
|
variable: "CLAUDE_SECURESTORAGE_CONFIG_DIR",
|
|
1630
1648
|
format: "claude",
|
|
1649
|
+
referenceName: "claude-code-login",
|
|
1631
1650
|
refreshArgs: ["-p", "/usage", "--setting-sources", "", "--no-session-persistence"],
|
|
1632
1651
|
renewWithin: "4 minutes"
|
|
1633
1652
|
},
|
|
1634
|
-
providerHosts:
|
|
1653
|
+
providerHosts: anthropicHosts,
|
|
1654
|
+
loginHosts: { claudeAiOauth: anthropicHosts },
|
|
1655
|
+
globalConfig: {
|
|
1656
|
+
file: ".claude.json",
|
|
1657
|
+
variable: "CLAUDE_CONFIG_DIR",
|
|
1658
|
+
keyField: "primaryApiKey",
|
|
1659
|
+
hosts: ["api.anthropic.com"],
|
|
1660
|
+
referenceName: "claude-api-key",
|
|
1661
|
+
links: { projects: ".claude/projects" }
|
|
1662
|
+
},
|
|
1635
1663
|
effortArgs: ["--effort", "{effort}"],
|
|
1636
1664
|
autoPermissionArgs: ["--dangerously-skip-permissions"],
|
|
1637
1665
|
requiredArgs: [
|
|
@@ -1710,6 +1738,19 @@ var HarnessAdapters = [
|
|
|
1710
1738
|
"generativelanguage.googleapis.com",
|
|
1711
1739
|
"openrouter.ai"
|
|
1712
1740
|
],
|
|
1741
|
+
loginHosts: {
|
|
1742
|
+
anthropic: ["api.anthropic.com"],
|
|
1743
|
+
openai: ["api.openai.com"],
|
|
1744
|
+
"openai-codex": ["chatgpt.com"],
|
|
1745
|
+
google: ["generativelanguage.googleapis.com"],
|
|
1746
|
+
"google-gemini-cli": ["cloudcode-pa.googleapis.com"],
|
|
1747
|
+
"github-copilot": githubCopilotHosts,
|
|
1748
|
+
openrouter: ["openrouter.ai"],
|
|
1749
|
+
groq: ["api.groq.com"],
|
|
1750
|
+
xai: ["api.x.ai"],
|
|
1751
|
+
mistral: ["api.mistral.ai"],
|
|
1752
|
+
cerebras: ["api.cerebras.ai"]
|
|
1753
|
+
},
|
|
1713
1754
|
effortArgs: ["--thinking", "{effort}"],
|
|
1714
1755
|
autoPermissionArgs: ["--no-approve"],
|
|
1715
1756
|
requiredArgs: ["--no-skills"],
|
|
@@ -1721,7 +1762,8 @@ var HarnessAdapters = [
|
|
|
1721
1762
|
variable: "PI_CODING_AGENT_DIR",
|
|
1722
1763
|
sessionsVariable: "PI_CODING_AGENT_SESSION_DIR",
|
|
1723
1764
|
operatorDir: ".pi/agent",
|
|
1724
|
-
copies: ["models
|
|
1765
|
+
copies: ["models-store.json"],
|
|
1766
|
+
providers: "models.json",
|
|
1725
1767
|
login: {
|
|
1726
1768
|
file: "auth.json",
|
|
1727
1769
|
refreshArgs: ["auth", "print-bearer-token", "--min-expiry", "15m", "--provider", "{provider}"],
|
|
@@ -1754,6 +1796,19 @@ var HarnessAdapters = [
|
|
|
1754
1796
|
"opencode.ai",
|
|
1755
1797
|
"models.dev"
|
|
1756
1798
|
],
|
|
1799
|
+
loginHosts: {
|
|
1800
|
+
anthropic: anthropicHosts,
|
|
1801
|
+
openai: ["api.openai.com", "auth.openai.com", "chatgpt.com"],
|
|
1802
|
+
opencode: ["opencode.ai"],
|
|
1803
|
+
google: ["generativelanguage.googleapis.com"],
|
|
1804
|
+
"github-copilot": githubCopilotHosts,
|
|
1805
|
+
openrouter: ["openrouter.ai"],
|
|
1806
|
+
groq: ["api.groq.com"],
|
|
1807
|
+
xai: ["api.x.ai"],
|
|
1808
|
+
mistral: ["api.mistral.ai"],
|
|
1809
|
+
cerebras: ["api.cerebras.ai"]
|
|
1810
|
+
},
|
|
1811
|
+
loginRefreshHosts: { "github-copilot": [...githubCopilotHosts, "api.github.com"] },
|
|
1757
1812
|
autoPermissionArgs: ["--auto"],
|
|
1758
1813
|
flagWhereListed: "--standalone",
|
|
1759
1814
|
mcp: { kind: "config_env", variable: "OPENCODE_CONFIG_CONTENT" },
|
|
@@ -1783,6 +1838,12 @@ function kitmanMcpToolTimeout(adapter, seconds) {
|
|
|
1783
1838
|
const value = timeout.unit === "ms" ? seconds * 1000 : seconds;
|
|
1784
1839
|
return timeout.kind === "env" ? { env: Object.fromEntries(timeout.variables.map((variable) => [variable, String(value)])) } : { server: { [timeout.field]: value } };
|
|
1785
1840
|
}
|
|
1841
|
+
var harnessNetworkHosts = (adapter) => [
|
|
1842
|
+
...new Set([
|
|
1843
|
+
...adapter?.providerHosts ?? [],
|
|
1844
|
+
...[adapter?.loginHosts, adapter?.loginRefreshHosts].flatMap((hosts) => Object.values(hosts ?? {}).flat())
|
|
1845
|
+
])
|
|
1846
|
+
];
|
|
1786
1847
|
var providerKeyHosts = new Map([
|
|
1787
1848
|
["ANTHROPIC_API_KEY", ["api.anthropic.com"]],
|
|
1788
1849
|
["ANTHROPIC_AUTH_TOKEN", ["api.anthropic.com", "console.anthropic.com", "claude.ai"]],
|
|
@@ -1803,18 +1864,53 @@ function resolveHarnessLaunch(input) {
|
|
|
1803
1864
|
const launch = input.adapter.env === undefined ? kit : { ...kit, env: { ...input.adapter.env, ...kit.env } };
|
|
1804
1865
|
const effort = input.effort;
|
|
1805
1866
|
const effortful = effort === undefined || input.adapter.effortArgs === undefined ? launch : { ...launch, args: [...launch.args, ...input.adapter.effortArgs.map((arg) => arg.replace("{effort}", effort))] };
|
|
1806
|
-
return flagProbedLaunch(input.adapter, sandboxHomeLaunch(input, effortful));
|
|
1807
|
-
}
|
|
1808
|
-
var sandboxedLaunch = (launch, backend) =>
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1867
|
+
return flagProbedLaunch(input.adapter, globalConfigLaunch(input, sandboxHomeLaunch(input, effortful)));
|
|
1868
|
+
}
|
|
1869
|
+
var sandboxedLaunch = (launch, backend) => {
|
|
1870
|
+
const sandboxed = launch.sandboxed;
|
|
1871
|
+
if (sandboxed === undefined)
|
|
1872
|
+
return launch;
|
|
1873
|
+
const srt = backend === "srt";
|
|
1874
|
+
const config = srt ? sandboxed.globalConfig : undefined;
|
|
1875
|
+
return {
|
|
1876
|
+
...launch,
|
|
1877
|
+
env: {
|
|
1878
|
+
...launch.env,
|
|
1879
|
+
...sandboxed.env,
|
|
1880
|
+
...srt && sandboxed.configHome !== undefined ? { XDG_CONFIG_HOME: sandboxed.configHome } : undefined,
|
|
1881
|
+
...config === undefined ? undefined : config.env
|
|
1882
|
+
},
|
|
1883
|
+
...sandboxed.login === undefined ? undefined : { renewedLogin: sandboxed.login },
|
|
1884
|
+
...sandboxed.homeDirectory === undefined ? undefined : { homeDirectory: sandboxed.homeDirectory },
|
|
1885
|
+
...config === undefined ? undefined : { globalConfig: config }
|
|
1886
|
+
};
|
|
1817
1887
|
};
|
|
1888
|
+
function globalConfigLaunch(input, launch) {
|
|
1889
|
+
const config = input.adapter.globalConfig;
|
|
1890
|
+
if (config === undefined)
|
|
1891
|
+
return launch;
|
|
1892
|
+
const home = input.home ?? homedir();
|
|
1893
|
+
const directory = `${input.configDir}/global-config`;
|
|
1894
|
+
return {
|
|
1895
|
+
...launch,
|
|
1896
|
+
sandboxed: {
|
|
1897
|
+
env: {},
|
|
1898
|
+
...launch.sandboxed,
|
|
1899
|
+
globalConfig: {
|
|
1900
|
+
env: { [config.variable]: directory },
|
|
1901
|
+
path: `${directory}/${config.file}`,
|
|
1902
|
+
source: `${home}/${config.file}`,
|
|
1903
|
+
keyField: config.keyField,
|
|
1904
|
+
hosts: config.hosts,
|
|
1905
|
+
referenceName: config.referenceName,
|
|
1906
|
+
links: Object.entries(config.links).map(([name, target]) => ({
|
|
1907
|
+
path: `${directory}/${name}`,
|
|
1908
|
+
target: `${home}/${target}`
|
|
1909
|
+
}))
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
};
|
|
1913
|
+
}
|
|
1818
1914
|
function sandboxHomeLaunch(input, launch) {
|
|
1819
1915
|
const { sandboxHome } = input.adapter;
|
|
1820
1916
|
if (sandboxHome === undefined)
|
|
@@ -1828,7 +1924,13 @@ function sandboxHomeLaunch(input, launch) {
|
|
|
1828
1924
|
configHome,
|
|
1829
1925
|
login: {
|
|
1830
1926
|
path: `${input.configDir}/${sandboxHome.login.path}`,
|
|
1831
|
-
source: `${home}/${sandboxHome.login.source}
|
|
1927
|
+
source: `${home}/${sandboxHome.login.source}`,
|
|
1928
|
+
format: "opencode",
|
|
1929
|
+
binary: input.adapter.binary,
|
|
1930
|
+
hosts: input.adapter.loginHosts ?? {},
|
|
1931
|
+
refreshTokenHosts: input.adapter.loginRefreshHosts ?? {},
|
|
1932
|
+
referenceName: `${input.adapter.id}-login`,
|
|
1933
|
+
refresh: { args: [], env: {}, within: "10 minutes" }
|
|
1832
1934
|
},
|
|
1833
1935
|
homeDirectory: `${configHome}/${sandboxHome.configHomeDirectory}`
|
|
1834
1936
|
}
|
|
@@ -1868,6 +1970,9 @@ function agentDirLaunch(input, launch) {
|
|
|
1868
1970
|
path: `${directory}/${agentDir.login.file}`,
|
|
1869
1971
|
source: `${operator}/${agentDir.login.file}`,
|
|
1870
1972
|
format: "pi",
|
|
1973
|
+
binary: input.adapter.binary,
|
|
1974
|
+
hosts: input.adapter.loginHosts ?? {},
|
|
1975
|
+
referenceName: `${input.adapter.id}-login`,
|
|
1871
1976
|
refresh: {
|
|
1872
1977
|
args: agentDir.login.refreshArgs,
|
|
1873
1978
|
env: { [agentDir.variable]: operator },
|
|
@@ -1878,6 +1983,14 @@ function agentDirLaunch(input, launch) {
|
|
|
1878
1983
|
path: `${directory}/${agentDir.settings.file}`,
|
|
1879
1984
|
source: `${operator}/${agentDir.settings.file}`,
|
|
1880
1985
|
keys: agentDir.settings.keys
|
|
1986
|
+
},
|
|
1987
|
+
...agentDir.providers === undefined ? undefined : {
|
|
1988
|
+
providers: {
|
|
1989
|
+
path: `${directory}/${agentDir.providers}`,
|
|
1990
|
+
source: `${operator}/${agentDir.providers}`,
|
|
1991
|
+
hosts: input.adapter.loginHosts ?? {},
|
|
1992
|
+
referenceName: `${input.adapter.id}-provider`
|
|
1993
|
+
}
|
|
1881
1994
|
}
|
|
1882
1995
|
}
|
|
1883
1996
|
};
|
|
@@ -1894,6 +2007,9 @@ function renewedLoginLaunch(input, launch) {
|
|
|
1894
2007
|
path: directory,
|
|
1895
2008
|
source: `${input.home ?? homedir()}/${login.operatorDir}/${login.file}`,
|
|
1896
2009
|
format: login.format,
|
|
2010
|
+
binary: input.adapter.binary,
|
|
2011
|
+
hosts: input.adapter.loginHosts ?? {},
|
|
2012
|
+
referenceName: login.referenceName,
|
|
1897
2013
|
linksDirectory: true,
|
|
1898
2014
|
refresh: { args: login.refreshArgs, env: {}, within: login.renewWithin }
|
|
1899
2015
|
}
|
|
@@ -2100,6 +2216,189 @@ function mcpLaunch(input, skillsDir) {
|
|
|
2100
2216
|
};
|
|
2101
2217
|
}
|
|
2102
2218
|
}
|
|
2219
|
+
// packages/agent-runtime/src/opencode-login.ts
|
|
2220
|
+
class OpenCodeLoginNotRenewed extends TaggedError("OpenCodeLoginNotRenewed") {
|
|
2221
|
+
get message() {
|
|
2222
|
+
return `OpenCode's ${this.provider} login was not renewed: ${this.reason}`;
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
var StoredCredential = Struct({
|
|
2226
|
+
id: String4,
|
|
2227
|
+
integrationID: String4,
|
|
2228
|
+
label: optionalKey(NullOr(String4)),
|
|
2229
|
+
value: Record(String4, Json),
|
|
2230
|
+
active: optionalKey(Boolean2)
|
|
2231
|
+
});
|
|
2232
|
+
var decodeExport = decodeUnknownOption(fromJsonString(ArraySchema(Json)));
|
|
2233
|
+
var decodeStored = decodeUnknownOption(StoredCredential);
|
|
2234
|
+
var RenewableLogin = Struct({
|
|
2235
|
+
type: Literal("oauth"),
|
|
2236
|
+
access: String4,
|
|
2237
|
+
refresh: NonEmptyString,
|
|
2238
|
+
expires: Finite.check(isGreaterThan(0))
|
|
2239
|
+
});
|
|
2240
|
+
var decodeRenewable = decodeUnknownOption(RenewableLogin);
|
|
2241
|
+
var TokenAnswer = Struct({
|
|
2242
|
+
access_token: String4,
|
|
2243
|
+
refresh_token: optionalKey(String4),
|
|
2244
|
+
expires_in: Finite
|
|
2245
|
+
});
|
|
2246
|
+
var XaiAnswer = Struct({
|
|
2247
|
+
access_token: String4,
|
|
2248
|
+
refresh_token: optionalKey(String4),
|
|
2249
|
+
expires_in: optionalKey(Finite)
|
|
2250
|
+
});
|
|
2251
|
+
var JwtExpiry = fromJsonString(Struct({ exp: Finite }));
|
|
2252
|
+
var decodeJwtExpiry = decodeUnknownOption(JwtExpiry);
|
|
2253
|
+
var CopilotAnswer = Struct({ token: String4, expires_at: Finite });
|
|
2254
|
+
var legacyCredential = (value) => {
|
|
2255
|
+
const metadata = isJsonObject(value.metadata) ? value.metadata : {};
|
|
2256
|
+
const strings = Object.fromEntries(Object.entries(metadata).filter(([, entry]) => isString(entry)));
|
|
2257
|
+
const carried = Object.keys(strings).length > 0 ? { metadata: strings } : undefined;
|
|
2258
|
+
if (value.type === "oauth")
|
|
2259
|
+
return Object.assign({ type: "oauth", refresh: value.refresh ?? "", access: value.access ?? "", expires: value.expires ?? 0 }, isString(metadata.accountID) ? { accountId: metadata.accountID } : undefined, isString(metadata.enterpriseUrl) ? { enterpriseUrl: metadata.enterpriseUrl } : undefined, carried);
|
|
2260
|
+
return value.type === "key" && isString(value.key) ? Object.assign({ type: "api", key: value.key }, carried) : undefined;
|
|
2261
|
+
};
|
|
2262
|
+
var activeCredentials = (entries) => {
|
|
2263
|
+
const chosen = {};
|
|
2264
|
+
for (const entry of entries)
|
|
2265
|
+
if (chosen[entry.integrationID] === undefined || entry.active === true && chosen[entry.integrationID]?.active !== true)
|
|
2266
|
+
chosen[entry.integrationID] = entry;
|
|
2267
|
+
return chosen;
|
|
2268
|
+
};
|
|
2269
|
+
var fileCredentials = (source) => gen(function* () {
|
|
2270
|
+
const text = yield* (yield* FileSystem).readFileString(source).pipe(orElseSucceed(() => ""));
|
|
2271
|
+
const credentials = getOrUndefined(decodeJsonStringOption(text));
|
|
2272
|
+
return isJsonObject(credentials) ? credentials : undefined;
|
|
2273
|
+
});
|
|
2274
|
+
var openCodeStore = (source) => gen(function* () {
|
|
2275
|
+
const path = yield* Path;
|
|
2276
|
+
const store = path.join(path.dirname(source), "opencode.db");
|
|
2277
|
+
const exists = yield* (yield* FileSystem).exists(store).pipe(orElseSucceed(() => false));
|
|
2278
|
+
return exists ? { env: { XDG_DATA_HOME: path.dirname(path.dirname(source)) } } : undefined;
|
|
2279
|
+
});
|
|
2280
|
+
var runOpenCode = (binary, store, args) => runCommand2(binary, [...args, "--standalone"], { env: store.env, timeout: "30 seconds" });
|
|
2281
|
+
var readOpenCodeLogin = (binary, source) => gen(function* () {
|
|
2282
|
+
const store = yield* openCodeStore(source);
|
|
2283
|
+
const exported = store === undefined ? none() : yield* runOpenCode(binary, store, ["auth", "export"]).pipe(map8(decodeExport), orElseSucceed(() => none()));
|
|
2284
|
+
if (isNone(exported)) {
|
|
2285
|
+
const credentials = yield* fileCredentials(source);
|
|
2286
|
+
return credentials === undefined ? undefined : { credentials };
|
|
2287
|
+
}
|
|
2288
|
+
const stored = activeCredentials(exported.value.flatMap((entry) => toArray(decodeStored(entry))));
|
|
2289
|
+
const credentials = Object.fromEntries(Object.entries(stored).flatMap(([provider, entry]) => {
|
|
2290
|
+
const legacy = legacyCredential(entry.value);
|
|
2291
|
+
return legacy === undefined ? [] : [[provider, legacy]];
|
|
2292
|
+
}));
|
|
2293
|
+
return { credentials, stored };
|
|
2294
|
+
});
|
|
2295
|
+
var answer = (provider, schema, request) => gen(function* () {
|
|
2296
|
+
const response = yield* (yield* HttpClient).execute(request);
|
|
2297
|
+
const ok = yield* filterStatusOk(response);
|
|
2298
|
+
return yield* schemaBodyJson(schema)(ok);
|
|
2299
|
+
}).pipe(mapError2((error) => new OpenCodeLoginNotRenewed({ provider, reason: error.message })));
|
|
2300
|
+
var refreshed = (now) => (answered) => ({
|
|
2301
|
+
access: answered.access_token,
|
|
2302
|
+
...answered.refresh_token === undefined ? undefined : { refresh: answered.refresh_token },
|
|
2303
|
+
expires: now + answered.expires_in * 1000
|
|
2304
|
+
});
|
|
2305
|
+
var xaiExpiry = (answered, now) => {
|
|
2306
|
+
if (answered.expires_in !== undefined && answered.expires_in > 0)
|
|
2307
|
+
return now + answered.expires_in * 1000;
|
|
2308
|
+
const payload = answered.access_token.split(".")[1];
|
|
2309
|
+
const exp = payload === undefined ? none() : decodeJwtExpiry(Buffer.from(payload, "base64url").toString());
|
|
2310
|
+
return match(exp, { onNone: () => now + 3600000, onSome: ({ exp }) => exp * 1000 });
|
|
2311
|
+
};
|
|
2312
|
+
var openCodeConsole = "https://opencode.ai/console";
|
|
2313
|
+
var consoleServer = (metadata) => (isString(metadata.server) ? metadata.server : openCodeConsole).replace(/^https:\/\/console\.opencode\.ai(?=\/|$)/, openCodeConsole);
|
|
2314
|
+
var consoleMetadata = (credential) => isJsonObject(credential) && isJsonObject(credential.metadata) ? credential.metadata : {};
|
|
2315
|
+
var openCodeConsoleHosts = (credentials) => {
|
|
2316
|
+
if (credentials?.opencode === undefined)
|
|
2317
|
+
return [];
|
|
2318
|
+
const server = liftThrowable(() => new URL(consoleServer(consoleMetadata(credentials.opencode))))();
|
|
2319
|
+
return match(filter2(server, (url) => url.protocol === "https:"), {
|
|
2320
|
+
onNone: () => [],
|
|
2321
|
+
onSome: (url) => [url.host]
|
|
2322
|
+
});
|
|
2323
|
+
};
|
|
2324
|
+
var openCodeConsoleKey = (credential) => Object.assign({ type: "api", key: credential.access ?? "" }, isJsonObject(credential.metadata) ? { metadata: credential.metadata } : undefined);
|
|
2325
|
+
var renewers = {
|
|
2326
|
+
anthropic: (login, now) => answer("anthropic", TokenAnswer, post("https://platform.claude.com/v1/oauth/token").pipe(bodyJsonUnsafe({
|
|
2327
|
+
grant_type: "refresh_token",
|
|
2328
|
+
refresh_token: login.refresh,
|
|
2329
|
+
client_id: "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
|
|
2330
|
+
}))).pipe(map8(refreshed(now))),
|
|
2331
|
+
openai: (login, now) => answer("openai", TokenAnswer, post("https://auth.openai.com/oauth/token").pipe(bodyUrlParams({
|
|
2332
|
+
grant_type: "refresh_token",
|
|
2333
|
+
refresh_token: login.refresh,
|
|
2334
|
+
client_id: "app_EMoamEEZ73f0CkXaXp7hrann"
|
|
2335
|
+
}))).pipe(map8(refreshed(now))),
|
|
2336
|
+
xai: (login, now) => answer("xai", XaiAnswer, post("https://auth.x.ai/oauth2/token").pipe(acceptJson, bodyUrlParams({
|
|
2337
|
+
grant_type: "refresh_token",
|
|
2338
|
+
refresh_token: login.refresh,
|
|
2339
|
+
client_id: "b1a00492-073a-47ea-816f-4c329264a828"
|
|
2340
|
+
}))).pipe(map8((answered) => ({
|
|
2341
|
+
access: answered.access_token,
|
|
2342
|
+
...answered.refresh_token === undefined ? undefined : { refresh: answered.refresh_token },
|
|
2343
|
+
expires: xaiExpiry(answered, now)
|
|
2344
|
+
}))),
|
|
2345
|
+
opencode: (login, now, metadata) => answer("opencode", TokenAnswer, post(`${consoleServer(metadata)}/auth/device/token`).pipe(acceptJson, bodyJsonUnsafe({
|
|
2346
|
+
grant_type: "refresh_token",
|
|
2347
|
+
refresh_token: login.refresh,
|
|
2348
|
+
client_id: "opencode-cli"
|
|
2349
|
+
}))).pipe(map8(refreshed(now))),
|
|
2350
|
+
"github-copilot": (login) => answer("github-copilot", CopilotAnswer, get("https://api.github.com/copilot_internal/v2/token").pipe(setHeaders({ authorization: `Bearer ${login.refresh}`, accept: "application/json" }))).pipe(map8((answered) => ({ access: answered.token, expires: answered.expires_at * 1000 })))
|
|
2351
|
+
};
|
|
2352
|
+
var renewerFor = (provider) => isKeyOf(renewers, provider) ? renewers[provider] : undefined;
|
|
2353
|
+
var renewableLogin = (provider, credential) => getOrUndefined(filter2(decodeRenewable(credential), (login) => renewerFor(provider) !== undefined && (provider !== "github-copilot" || login.access !== login.refresh)));
|
|
2354
|
+
var renewsOpenCodeCredential = (provider, credential) => renewableLogin(provider, credential) !== undefined;
|
|
2355
|
+
var openCodeExpiry = (credentials, provider) => renewableLogin(provider, credentials?.[provider])?.expires;
|
|
2356
|
+
var replaceStored = (binary, source, store, stored, value) => gen(function* () {
|
|
2357
|
+
const fs = yield* FileSystem;
|
|
2358
|
+
const path = yield* Path;
|
|
2359
|
+
const directory = yield* fs.makeTempDirectoryScoped({
|
|
2360
|
+
directory: path.dirname(source),
|
|
2361
|
+
prefix: "kitman-opencode-renewal-"
|
|
2362
|
+
});
|
|
2363
|
+
const file = path.join(directory, "credentials.json");
|
|
2364
|
+
const id = `cred_kitman${(yield* currentTimeMillis).toString(36)}${Math.abs(yield* nextInt).toString(36)}`;
|
|
2365
|
+
yield* fs.writeFileString(file, encodeUnknownJsonStringSync([
|
|
2366
|
+
{ id, integrationID: stored.integrationID, label: stored.label ?? "", value, active: true }
|
|
2367
|
+
]), { mode: 384 });
|
|
2368
|
+
yield* runOpenCode(binary, store, ["auth", "import", file]);
|
|
2369
|
+
yield* runOpenCode(binary, store, ["api", "credential.activate", "--param", `credentialID=${id}`]);
|
|
2370
|
+
yield* runOpenCode(binary, store, ["api", "credential.remove", "--param", `credentialID=${stored.id}`]);
|
|
2371
|
+
}).pipe(scoped);
|
|
2372
|
+
var replaceInFile = (source, provider, credential) => gen(function* () {
|
|
2373
|
+
const fs = yield* FileSystem;
|
|
2374
|
+
const current = (yield* fileCredentials(source)) ?? {};
|
|
2375
|
+
const next = `${source}.${Math.abs(yield* nextInt)}.kitman-next`;
|
|
2376
|
+
yield* fs.writeFileString(next, encodeUnknownJsonStringSync(Object.assign({}, current, { [provider]: credential })), { mode: 384 });
|
|
2377
|
+
yield* fs.rename(next, source);
|
|
2378
|
+
});
|
|
2379
|
+
var renewalPermits = new Map;
|
|
2380
|
+
var oneRenewalAt = (source) => (effect) => {
|
|
2381
|
+
const permit = renewalPermits.get(source) ?? makeUnsafe3(1);
|
|
2382
|
+
renewalPermits.set(source, permit);
|
|
2383
|
+
return permit.withPermits(1)(effect);
|
|
2384
|
+
};
|
|
2385
|
+
var renewOpenCodeLogin = (binary, source, provider, seenExpiry) => gen(function* () {
|
|
2386
|
+
const login = yield* readOpenCodeLogin(binary, source);
|
|
2387
|
+
const credential = login?.credentials[provider];
|
|
2388
|
+
const renewable = renewableLogin(provider, credential);
|
|
2389
|
+
const renew = renewerFor(provider);
|
|
2390
|
+
if (login === undefined || renewable === undefined || renew === undefined || !isJsonObject(credential))
|
|
2391
|
+
return yield* new OpenCodeLoginNotRenewed({ provider, reason: "it holds no OAuth login the Runner renews" });
|
|
2392
|
+
if (seenExpiry !== undefined && renewable.expires > seenExpiry)
|
|
2393
|
+
return;
|
|
2394
|
+
const stored = login.stored?.[provider];
|
|
2395
|
+
const metadata = isJsonObject(stored?.value.metadata) ? stored.value.metadata : {};
|
|
2396
|
+
const renewed = yield* renew(renewable, yield* currentTimeMillis, metadata);
|
|
2397
|
+
const tokens = { access: renewed.access, refresh: renewed.refresh ?? renewable.refresh, expires: renewed.expires };
|
|
2398
|
+
const store = yield* openCodeStore(source);
|
|
2399
|
+
yield* (stored === undefined || store === undefined ? replaceInFile(source, provider, Object.assign({}, credential, tokens)) : replaceStored(binary, source, store, stored, Object.assign({}, stored.value, tokens))).pipe(mapError2((error) => new OpenCodeLoginNotRenewed({ provider, reason: error.message })));
|
|
2400
|
+
}).pipe(oneRenewalAt(source));
|
|
2401
|
+
|
|
2103
2402
|
// packages/agent-runtime/src/skill-fits.ts
|
|
2104
2403
|
import { matchesGlob } from "path";
|
|
2105
2404
|
var skipped = new Set([".git", "node_modules"]);
|
|
@@ -2186,13 +2485,17 @@ var stepSandboxPolicy = (input) => ({
|
|
|
2186
2485
|
readDeniedPaths: [
|
|
2187
2486
|
...input.policy.readDeniedPaths,
|
|
2188
2487
|
...HarnessAdapters.filter((other) => other.id !== input.adapter.id).flatMap((other) => other.auth),
|
|
2189
|
-
...input.adapter.agentDir === undefined ? [] : [
|
|
2488
|
+
...input.adapter.agentDir === undefined ? [] : [
|
|
2489
|
+
input.adapter.agentDir.login.file,
|
|
2490
|
+
...input.adapter.agentDir.providers === undefined ? [] : [input.adapter.agentDir.providers]
|
|
2491
|
+
].map((file) => `~/${input.adapter.agentDir?.operatorDir}/${file}`),
|
|
2190
2492
|
...input.adapter.renewedLogin === undefined ? [] : [`~/${input.adapter.renewedLogin.operatorDir}/${input.adapter.renewedLogin.file}`],
|
|
2191
|
-
...input.adapter.sandboxHome === undefined ? [] : [`~/${input.adapter.sandboxHome.login.source}`]
|
|
2493
|
+
...input.adapter.sandboxHome === undefined ? [] : [`~/${input.adapter.sandboxHome.login.source.replace(/\/[^/]+$/, "")}`],
|
|
2494
|
+
...input.launch?.globalConfig === undefined ? [] : [input.launch.globalConfig.source]
|
|
2192
2495
|
],
|
|
2193
2496
|
readAllowedPaths: [
|
|
2194
2497
|
...input.policy.readAllowedPaths,
|
|
2195
|
-
...input.adapter.loginFiles ?? [],
|
|
2498
|
+
...input.launch?.globalConfig === undefined ? input.adapter.loginFiles ?? [] : [],
|
|
2196
2499
|
input.workspace,
|
|
2197
2500
|
input.configDir
|
|
2198
2501
|
],
|
|
@@ -2297,8 +2600,90 @@ var credentialsIn = (source) => gen(function* () {
|
|
|
2297
2600
|
const credentials = getOrUndefined(decodeJsonStringOption(text));
|
|
2298
2601
|
return isJsonObject(credentials) ? credentials : undefined;
|
|
2299
2602
|
});
|
|
2603
|
+
var loginCredentials = (login) => login.format === "opencode" ? map8(readOpenCodeLogin(login.binary, login.source), (read) => read?.credentials) : credentialsIn(login.source);
|
|
2604
|
+
var neverExpires = 253402300799000;
|
|
2300
2605
|
var isOAuth = (credential) => isJsonObject(credential) && credential.type === "oauth";
|
|
2301
2606
|
var claudeOAuth = "claudeAiOauth";
|
|
2607
|
+
var piVariable = /\$(?:([$!])|\{([A-Za-z_]\w*)\}|([A-Za-z_]\w*))?/g;
|
|
2608
|
+
var isPiCommand = (value) => value.startsWith("!");
|
|
2609
|
+
var piResolved = (value, env = {}) => {
|
|
2610
|
+
if (isPiCommand(value))
|
|
2611
|
+
return;
|
|
2612
|
+
let resolved = true;
|
|
2613
|
+
const text = value.replace(piVariable, (dollar, escaped, braced, bare) => {
|
|
2614
|
+
const name = braced ?? bare;
|
|
2615
|
+
if (name === undefined)
|
|
2616
|
+
return escaped ?? dollar;
|
|
2617
|
+
const found = env[name];
|
|
2618
|
+
if (isString(found) && found !== "")
|
|
2619
|
+
return found;
|
|
2620
|
+
resolved = false;
|
|
2621
|
+
return dollar;
|
|
2622
|
+
});
|
|
2623
|
+
return resolved ? text : undefined;
|
|
2624
|
+
};
|
|
2625
|
+
var piNames = (value) => isPiCommand(value) ? [] : [...value.matchAll(piVariable)].flatMap((match) => match[2] ?? match[3] ?? []);
|
|
2626
|
+
var piConfiguringEnv = new Set([
|
|
2627
|
+
"AWS_BEDROCK_FORCE_CACHE",
|
|
2628
|
+
"AWS_DEFAULT_REGION",
|
|
2629
|
+
"AWS_REGION",
|
|
2630
|
+
"AZURE_OPENAI_API_VERSION",
|
|
2631
|
+
"AZURE_OPENAI_BASE_URL",
|
|
2632
|
+
"AZURE_OPENAI_DEPLOYMENT_NAME_MAP",
|
|
2633
|
+
"AZURE_OPENAI_RESOURCE_NAME",
|
|
2634
|
+
"CLOUDFLARE_ACCOUNT_ID",
|
|
2635
|
+
"CLOUDFLARE_GATEWAY_ID",
|
|
2636
|
+
"GCLOUD_PROJECT",
|
|
2637
|
+
"GOOGLE_CLOUD_LOCATION",
|
|
2638
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
2639
|
+
"PI_CACHE_RETENTION"
|
|
2640
|
+
]);
|
|
2641
|
+
var piKey = (key, credential) => piResolved(key, isJsonObject(credential.env) ? credential.env : {});
|
|
2642
|
+
var withConfiguringEnv = (credential, field) => {
|
|
2643
|
+
if (!isJsonObject(credential.env))
|
|
2644
|
+
return credential;
|
|
2645
|
+
const named = isString(credential[field]) ? piNames(credential[field]) : [];
|
|
2646
|
+
return Object.assign({}, credential, {
|
|
2647
|
+
env: Object.fromEntries(Object.entries(credential.env).filter(([name]) => piConfiguringEnv.has(name) && !named.includes(name)))
|
|
2648
|
+
});
|
|
2649
|
+
};
|
|
2650
|
+
var referenceNamePattern = /^[A-Za-z0-9_.-]+$/;
|
|
2651
|
+
var perProviderPlaceholders = (tokenFields, keyValue = (key) => key, isCommand = () => false) => (credentials, login, reference) => {
|
|
2652
|
+
const kept = [];
|
|
2653
|
+
const tokens = {};
|
|
2654
|
+
const held = (name, token, hosts) => {
|
|
2655
|
+
if (hosts.length > 0)
|
|
2656
|
+
tokens[name] = { value: token, hosts };
|
|
2657
|
+
return secretPlaceholder(token, name);
|
|
2658
|
+
};
|
|
2659
|
+
const placed = Object.entries(credentials).flatMap(([provider, credential]) => {
|
|
2660
|
+
const hosts = login.hosts[provider];
|
|
2661
|
+
const refreshHosts = login.refreshTokenHosts?.[provider];
|
|
2662
|
+
const field = isJsonObject(credential) && isString(credential.type) ? tokenFields[credential.type] : undefined;
|
|
2663
|
+
if (hosts === undefined && refreshHosts === undefined || field === undefined || !isJsonObject(credential) || !isString(credential[field]) || !referenceNamePattern.test(provider))
|
|
2664
|
+
return [];
|
|
2665
|
+
const token = credential.type === "oauth" ? credential[field] : keyValue(credential[field], credential);
|
|
2666
|
+
if (credential.type !== "oauth" && isCommand(credential[field]))
|
|
2667
|
+
return [];
|
|
2668
|
+
if (token === undefined) {
|
|
2669
|
+
kept.push([provider, withConfiguringEnv(credential, field)]);
|
|
2670
|
+
return [];
|
|
2671
|
+
}
|
|
2672
|
+
const name = reference(`${login.referenceName}-${provider}`);
|
|
2673
|
+
const refresh = isOAuth(credential) ? credential.refresh : undefined;
|
|
2674
|
+
const tokenHosts = [...new Set([...hosts ?? [], ...refreshHosts ?? []])];
|
|
2675
|
+
const heldRefresh = !isOAuth(credential) ? undefined : {
|
|
2676
|
+
refresh: refreshHosts !== undefined && isString(refresh) && refresh !== "" ? held(reference(`${login.referenceName}-${provider}-refresh`), refresh, refreshHosts) : ""
|
|
2677
|
+
};
|
|
2678
|
+
return [
|
|
2679
|
+
[
|
|
2680
|
+
provider,
|
|
2681
|
+
Object.assign({}, withConfiguringEnv(credential, field), { [field]: token === "" ? "" : held(name, token, tokenHosts) }, heldRefresh)
|
|
2682
|
+
]
|
|
2683
|
+
];
|
|
2684
|
+
});
|
|
2685
|
+
return { held: Object.fromEntries([...kept, ...placed]), tokens };
|
|
2686
|
+
};
|
|
2302
2687
|
var loginFormats = {
|
|
2303
2688
|
pi: {
|
|
2304
2689
|
expiry: (credentials, provider) => {
|
|
@@ -2309,6 +2694,7 @@ var loginFormats = {
|
|
|
2309
2694
|
provider,
|
|
2310
2695
|
isOAuth(credential) ? Object.assign({}, credential, { refresh: "" }) : credential
|
|
2311
2696
|
])),
|
|
2697
|
+
byReference: perProviderPlaceholders({ oauth: "access", api_key: "key" }, piKey, isPiCommand),
|
|
2312
2698
|
exitMeansRenewed: true
|
|
2313
2699
|
},
|
|
2314
2700
|
claude: {
|
|
@@ -2320,22 +2706,58 @@ var loginFormats = {
|
|
|
2320
2706
|
const credential = credentials[claudeOAuth];
|
|
2321
2707
|
return isJsonObject(credential) ? { [claudeOAuth]: Object.assign({}, credential, { refreshToken: "" }) } : undefined;
|
|
2322
2708
|
},
|
|
2709
|
+
byReference: (credentials, login, reference) => {
|
|
2710
|
+
const credential = credentials[claudeOAuth];
|
|
2711
|
+
const hosts = login.hosts[claudeOAuth];
|
|
2712
|
+
if (!isJsonObject(credential) || !isString(credential.accessToken) || hosts === undefined)
|
|
2713
|
+
return;
|
|
2714
|
+
const name = reference(login.referenceName);
|
|
2715
|
+
return {
|
|
2716
|
+
held: { [claudeOAuth]: Object.assign({}, credential, { accessToken: name, refreshToken: "" }) },
|
|
2717
|
+
tokens: { [name]: { value: credential.accessToken, hosts } }
|
|
2718
|
+
};
|
|
2719
|
+
},
|
|
2720
|
+
exitMeansRenewed: false
|
|
2721
|
+
},
|
|
2722
|
+
opencode: {
|
|
2723
|
+
expiry: openCodeExpiry,
|
|
2724
|
+
withoutRefresh: (credentials) => Object.fromEntries(Object.entries(credentials).map(([provider, credential]) => [
|
|
2725
|
+
provider,
|
|
2726
|
+
isOAuth(credential) ? Object.assign({}, credential, { refresh: "" }) : credential
|
|
2727
|
+
])),
|
|
2728
|
+
byReference: (credentials, login, reference) => {
|
|
2729
|
+
const consoleHosts = [...new Set([...login.hosts.opencode ?? [], ...openCodeConsoleHosts(credentials)])];
|
|
2730
|
+
const withConsole = { ...login, hosts: { ...login.hosts, opencode: consoleHosts } };
|
|
2731
|
+
const placeholders = perProviderPlaceholders({ oauth: "access", api: "key" });
|
|
2732
|
+
const { held, tokens } = placeholders(credentials, withConsole, reference);
|
|
2733
|
+
return {
|
|
2734
|
+
held: Object.fromEntries(Object.entries(held).map(([provider, credential]) => [
|
|
2735
|
+
provider,
|
|
2736
|
+
!isOAuth(credential) ? credential : provider === "opencode" ? openCodeConsoleKey(credential) : renewsOpenCodeCredential(provider, credentials[provider]) ? Object.assign({}, credential, { expires: neverExpires }) : credential
|
|
2737
|
+
])),
|
|
2738
|
+
tokens
|
|
2739
|
+
};
|
|
2740
|
+
},
|
|
2323
2741
|
exitMeansRenewed: false
|
|
2324
2742
|
}
|
|
2325
2743
|
};
|
|
2326
|
-
var refreshOperatorLogin = (
|
|
2744
|
+
var refreshOperatorLogin = (login, expired, http) => gen(function* () {
|
|
2327
2745
|
const format = loginFormats[login.format];
|
|
2328
2746
|
const now = yield* currentTimeMillis;
|
|
2329
2747
|
const expiringBefore = now + toMillis(login.refresh.within);
|
|
2330
|
-
const credentials = yield*
|
|
2748
|
+
const credentials = yield* loginCredentials(login);
|
|
2331
2749
|
const due = Object.keys(credentials ?? {}).flatMap((provider) => {
|
|
2332
2750
|
const expires = format.expiry(credentials, provider);
|
|
2333
2751
|
const waiting = (expired.get(provider)?.retryAt ?? 0) > now;
|
|
2334
2752
|
return expires === undefined || expires >= expiringBefore || expires <= now && waiting ? [] : [{ provider, expires }];
|
|
2335
2753
|
});
|
|
2336
2754
|
for (const { provider, expires } of due) {
|
|
2337
|
-
const
|
|
2338
|
-
|
|
2755
|
+
const renewal = login.format === "opencode" ? renewOpenCodeLogin(login.binary, login.source, provider, expires).pipe(provide3(http === undefined ? layer4 : succeed5(HttpClient, http)), as(true), orElseSucceed(() => false)) : runCommand2(login.binary, login.refresh.args.map((arg) => arg.replace("{provider}", provider)), {
|
|
2756
|
+
env: login.refresh.env,
|
|
2757
|
+
timeout: "30 seconds"
|
|
2758
|
+
}).pipe(as(true), orElseSucceed(() => false));
|
|
2759
|
+
const ran = yield* renewal.pipe(uninterruptible);
|
|
2760
|
+
if (ran && format.exitMeansRenewed || (format.expiry(yield* loginCredentials(login), provider) ?? expires) > expires) {
|
|
2339
2761
|
expired.delete(provider);
|
|
2340
2762
|
continue;
|
|
2341
2763
|
}
|
|
@@ -2346,37 +2768,35 @@ var refreshOperatorLogin = (binary, login, expired) => gen(function* () {
|
|
|
2346
2768
|
}
|
|
2347
2769
|
}
|
|
2348
2770
|
});
|
|
2349
|
-
var
|
|
2350
|
-
|
|
2351
|
-
return isJsonObject(credential) && isString(credential.accessToken) ? {
|
|
2352
|
-
token: credential.accessToken,
|
|
2353
|
-
held: { ...held, [claudeOAuth]: Object.assign({}, credential, { accessToken: reference }) }
|
|
2354
|
-
} : undefined;
|
|
2355
|
-
};
|
|
2356
|
-
var stepLogin = (login, reference) => map8(credentialsIn(login.source), (credentials) => {
|
|
2357
|
-
const held = credentials === undefined ? undefined : loginFormats[login.format].withoutRefresh(credentials);
|
|
2358
|
-
if (held === undefined)
|
|
2771
|
+
var stepLogin = (login, reference) => map8(loginCredentials(login), (credentials) => {
|
|
2772
|
+
if (credentials === undefined)
|
|
2359
2773
|
return;
|
|
2360
|
-
const
|
|
2361
|
-
|
|
2774
|
+
const format = loginFormats[login.format];
|
|
2775
|
+
if (reference === undefined) {
|
|
2776
|
+
const held = format.withoutRefresh(credentials);
|
|
2777
|
+
return held === undefined ? undefined : { content: encodeUnknownJsonStringSync(held), tokens: {} };
|
|
2778
|
+
}
|
|
2779
|
+
const held = format.byReference(credentials, login, reference);
|
|
2780
|
+
return held === undefined ? undefined : { content: encodeUnknownJsonStringSync(held.held), tokens: held.tokens };
|
|
2362
2781
|
});
|
|
2363
|
-
var renewableStepLogin = (
|
|
2782
|
+
var renewableStepLogin = (login, referenced, http) => gen(function* () {
|
|
2364
2783
|
const fs = yield* FileSystem;
|
|
2365
2784
|
const path = yield* Path;
|
|
2366
2785
|
const directory = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-login-" });
|
|
2367
2786
|
const file = path.join(directory, path.basename(login.source));
|
|
2368
2787
|
const expired = new Map;
|
|
2369
2788
|
let published;
|
|
2370
|
-
let
|
|
2789
|
+
let heldTokens;
|
|
2371
2790
|
const writing = makeUnsafe3(1);
|
|
2372
2791
|
const refreshing = makeUnsafe3(1);
|
|
2373
2792
|
const copy = gen(function* () {
|
|
2374
2793
|
const copied = yield* stepLogin(login, referenced?.reference);
|
|
2375
2794
|
if (copied === undefined)
|
|
2376
2795
|
return;
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2796
|
+
const tokens = encodeUnknownJsonStringSync(copied.tokens);
|
|
2797
|
+
if (referenced !== undefined && tokens !== heldTokens) {
|
|
2798
|
+
yield* referenced.hold(copied.tokens);
|
|
2799
|
+
heldTokens = tokens;
|
|
2380
2800
|
}
|
|
2381
2801
|
if (copied.content === published)
|
|
2382
2802
|
return;
|
|
@@ -2384,17 +2804,154 @@ var renewableStepLogin = (binary, login, referenced) => gen(function* () {
|
|
|
2384
2804
|
yield* fs.rename(`${file}.next`, file);
|
|
2385
2805
|
published = copied.content;
|
|
2386
2806
|
}).pipe((saving) => writing.withPermit(saving));
|
|
2387
|
-
const publish = (refresh) => refresh ? refreshing.withPermit(refreshOperatorLogin(
|
|
2807
|
+
const publish = (refresh) => refresh ? refreshing.withPermit(refreshOperatorLogin(login, expired, http)).pipe(andThen2(copy)) : copy;
|
|
2388
2808
|
return { directory, file, publish, isPublished: () => published !== undefined };
|
|
2389
2809
|
});
|
|
2810
|
+
var loopbackHosts = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
2811
|
+
var keyDestination = (baseUrl, fallback) => {
|
|
2812
|
+
if (!isString(baseUrl))
|
|
2813
|
+
return { hosts: fallback };
|
|
2814
|
+
const url = getOrUndefined(liftThrowable(() => new URL(baseUrl))());
|
|
2815
|
+
if (url?.protocol === "https:")
|
|
2816
|
+
return { hosts: [url.host] };
|
|
2817
|
+
return { hosts: undefined, local: url?.protocol === "http:" && loopbackHosts.has(url.hostname) };
|
|
2818
|
+
};
|
|
2819
|
+
var readProviders = (source) => gen(function* () {
|
|
2820
|
+
const fs = yield* FileSystem;
|
|
2821
|
+
const text = yield* fs.readFileString(source).pipe(orElseSucceed(() => {
|
|
2822
|
+
return;
|
|
2823
|
+
}));
|
|
2824
|
+
const config = text === undefined ? undefined : getOrUndefined(decodeJsonStringOption(text));
|
|
2825
|
+
return { text, config: isJsonObject(config) ? config : undefined };
|
|
2826
|
+
});
|
|
2827
|
+
var objectEntries = (value) => isJsonObject(value) ? Object.entries(value) : [];
|
|
2828
|
+
var inheritedDestination = (destinations) => {
|
|
2829
|
+
const hosts = [...new Set(destinations.flatMap(({ hosts }) => hosts ?? []))];
|
|
2830
|
+
return hosts.length > 0 ? { hosts } : { hosts: undefined, local: destinations.some(({ local }) => local === true) };
|
|
2831
|
+
};
|
|
2832
|
+
var providerDestinations = (config, hosts) => objectEntries(config?.providers).flatMap(([name, provider]) => {
|
|
2833
|
+
if (!isJsonObject(provider))
|
|
2834
|
+
return [];
|
|
2835
|
+
const destination = keyDestination(provider.baseUrl, hosts[name]);
|
|
2836
|
+
const models = (Array.isArray(provider.models) ? provider.models : []).map((model) => isJsonObject(model) && isString(model.baseUrl) ? keyDestination(model.baseUrl, destination.hosts) : destination);
|
|
2837
|
+
return [{ name, provider, destination, models, inherited: inheritedDestination([destination, ...models]) }];
|
|
2838
|
+
});
|
|
2839
|
+
var loginHostsWithProviders = (operatorFiles) => gen(function* () {
|
|
2840
|
+
const { login, providers } = operatorFiles;
|
|
2841
|
+
if (providers === undefined)
|
|
2842
|
+
return login;
|
|
2843
|
+
const { config } = yield* readProviders(providers.source);
|
|
2844
|
+
const hosts = {
|
|
2845
|
+
...login.hosts,
|
|
2846
|
+
...Object.fromEntries(providerDestinations(config, providers.hosts).flatMap(({ name, inherited }) => inherited.hosts !== undefined ? [[name, inherited.hosts]] : inherited.local === true ? [[name, []]] : []))
|
|
2847
|
+
};
|
|
2848
|
+
return { ...login, hosts };
|
|
2849
|
+
});
|
|
2850
|
+
var carriedLoginHosts = (launch) => launch.renewedLogin?.format === "opencode" ? map8(loginCredentials(launch.renewedLogin), openCodeConsoleHosts) : succeed6([]);
|
|
2851
|
+
var carriedProviderHosts = (launch) => gen(function* () {
|
|
2852
|
+
const providers = launch.operatorFiles?.providers;
|
|
2853
|
+
if (providers === undefined)
|
|
2854
|
+
return [];
|
|
2855
|
+
const { config } = yield* readProviders(providers.source);
|
|
2856
|
+
return [
|
|
2857
|
+
...new Set(providerDestinations(config, providers.hosts).flatMap(({ destination, models }) => [destination, ...models].flatMap(({ hosts }) => hosts ?? [])))
|
|
2858
|
+
];
|
|
2859
|
+
});
|
|
2860
|
+
var carriedProviders = (providers, referenced) => gen(function* () {
|
|
2861
|
+
const { text, config } = yield* readProviders(providers.source);
|
|
2862
|
+
if (text === undefined)
|
|
2863
|
+
return [];
|
|
2864
|
+
if (referenced === undefined)
|
|
2865
|
+
return [{ path: providers.path, content: text }];
|
|
2866
|
+
if (config === undefined || !isJsonObject(config.providers))
|
|
2867
|
+
return [{ path: providers.path, content: "{}" }];
|
|
2868
|
+
const tokens = {};
|
|
2869
|
+
const placeholder = (field, value, destination) => {
|
|
2870
|
+
if (!isString(value))
|
|
2871
|
+
return value;
|
|
2872
|
+
if (isPiCommand(value))
|
|
2873
|
+
return;
|
|
2874
|
+
const literal = piResolved(value);
|
|
2875
|
+
if (literal === undefined)
|
|
2876
|
+
return value;
|
|
2877
|
+
if (destination.hosts === undefined && destination.local !== true)
|
|
2878
|
+
return;
|
|
2879
|
+
const reference = referenced.reference(`${providers.referenceName}-${Object.keys(tokens).length}-${field}`.replace(/[^A-Za-z0-9_.-]/g, "-"));
|
|
2880
|
+
if (destination.hosts !== undefined)
|
|
2881
|
+
tokens[reference] = { value: literal, hosts: destination.hosts };
|
|
2882
|
+
return secretPlaceholder(literal, reference);
|
|
2883
|
+
};
|
|
2884
|
+
const heldEntry = (entry, field, destination) => {
|
|
2885
|
+
const { apiKey, headers, ...rest } = entry;
|
|
2886
|
+
const heldHeaders = isJsonObject(headers) ? Object.fromEntries(Object.entries(headers).flatMap(([header, value]) => {
|
|
2887
|
+
const kept = placeholder(`${field}-header-${header}`, value, destination);
|
|
2888
|
+
return kept === undefined ? [] : [[header, kept]];
|
|
2889
|
+
})) : undefined;
|
|
2890
|
+
const key = placeholder(`${field}-key`, apiKey, destination);
|
|
2891
|
+
return {
|
|
2892
|
+
...rest,
|
|
2893
|
+
...key === undefined ? undefined : { apiKey: key },
|
|
2894
|
+
...heldHeaders === undefined ? undefined : { headers: heldHeaders }
|
|
2895
|
+
};
|
|
2896
|
+
};
|
|
2897
|
+
const held = Object.fromEntries(providerDestinations(config, providers.hosts).map(({ name, provider, destination, models, inherited }) => {
|
|
2898
|
+
const entry = heldEntry(provider, name, inherited);
|
|
2899
|
+
const heldModels = Array.isArray(provider.models) ? provider.models.map((model, index) => isJsonObject(model) ? heldEntry(model, `${name}-model-${index}`, models[index] ?? destination) : model) : undefined;
|
|
2900
|
+
const overrides = isJsonObject(provider.modelOverrides) ? Object.fromEntries(Object.entries(provider.modelOverrides).map(([id, override]) => [
|
|
2901
|
+
id,
|
|
2902
|
+
isJsonObject(override) ? heldEntry(override, `${name}-override-${id}`, destination) : override
|
|
2903
|
+
])) : undefined;
|
|
2904
|
+
return [
|
|
2905
|
+
name,
|
|
2906
|
+
{
|
|
2907
|
+
...entry,
|
|
2908
|
+
...heldModels === undefined ? undefined : { models: heldModels },
|
|
2909
|
+
...overrides === undefined ? undefined : { modelOverrides: overrides }
|
|
2910
|
+
}
|
|
2911
|
+
];
|
|
2912
|
+
}));
|
|
2913
|
+
yield* referenced.hold(tokens);
|
|
2914
|
+
return [
|
|
2915
|
+
{ path: providers.path, content: encodeUnknownJsonStringSync(Object.assign({}, config, { providers: held })) }
|
|
2916
|
+
];
|
|
2917
|
+
});
|
|
2918
|
+
var withoutMcpServers = (config) => {
|
|
2919
|
+
const { mcpServers: _servers, projects, ...rest } = config;
|
|
2920
|
+
if (!isJsonObject(projects))
|
|
2921
|
+
return projects === undefined ? rest : { ...rest, projects };
|
|
2922
|
+
return {
|
|
2923
|
+
...rest,
|
|
2924
|
+
projects: Object.fromEntries(Object.entries(projects).map(([directory, project]) => {
|
|
2925
|
+
if (!isJsonObject(project))
|
|
2926
|
+
return [directory, project];
|
|
2927
|
+
const { mcpServers: _projectServers, ...kept } = project;
|
|
2928
|
+
return [directory, kept];
|
|
2929
|
+
}))
|
|
2930
|
+
};
|
|
2931
|
+
};
|
|
2932
|
+
var carriedGlobalConfig = (config, referenced) => gen(function* () {
|
|
2933
|
+
const operator = yield* credentialsIn(config.source);
|
|
2934
|
+
if (operator === undefined)
|
|
2935
|
+
return [];
|
|
2936
|
+
const { [config.keyField]: key, ...rest } = withoutMcpServers(operator);
|
|
2937
|
+
if (!isString(key) || referenced === undefined)
|
|
2938
|
+
return [{ path: config.path, content: encodeUnknownJsonStringSync(rest) }];
|
|
2939
|
+
const reference = referenced.reference(config.referenceName);
|
|
2940
|
+
yield* referenced.hold({ [reference]: { value: key, hosts: config.hosts } });
|
|
2941
|
+
return [
|
|
2942
|
+
{
|
|
2943
|
+
path: config.path,
|
|
2944
|
+
content: encodeUnknownJsonStringSync({ ...rest, [config.keyField]: secretPlaceholder(key, reference) })
|
|
2945
|
+
}
|
|
2946
|
+
];
|
|
2947
|
+
});
|
|
2390
2948
|
var writeHarnessFiles = (input) => gen(function* () {
|
|
2391
2949
|
const fs = yield* FileSystem;
|
|
2392
2950
|
const path = yield* Path;
|
|
2393
2951
|
const unwritable = harnessConfigUnwritable();
|
|
2394
2952
|
const carried = input.carryOperatorFiles ? input.launch.operatorFiles : undefined;
|
|
2395
|
-
const
|
|
2396
|
-
const
|
|
2397
|
-
const login = renewed === undefined ? undefined : yield* renewableStepLogin(input.launch.binary, renewed, input.loginReference).pipe(orDie);
|
|
2953
|
+
const renewed = !input.carryOperatorFiles ? undefined : carried === undefined ? input.launch.renewedLogin : yield* loginHostsWithProviders(carried);
|
|
2954
|
+
const login = renewed === undefined ? undefined : yield* renewableStepLogin(renewed, input.loginReference, input.loginHttp).pipe(orDie);
|
|
2398
2955
|
if (login !== undefined)
|
|
2399
2956
|
yield* login.publish(true).pipe(mapError2(() => unwritable));
|
|
2400
2957
|
const settings = carried === undefined ? [] : [
|
|
@@ -2403,11 +2960,14 @@ var writeHarnessFiles = (input) => gen(function* () {
|
|
|
2403
2960
|
content: encodeUnknownJsonStringSync(yield* carriedSettings(carried.settings.source, carried.settings.keys))
|
|
2404
2961
|
}
|
|
2405
2962
|
];
|
|
2406
|
-
const
|
|
2407
|
-
const
|
|
2408
|
-
const
|
|
2963
|
+
const providers = carried?.providers === undefined ? [] : yield* carriedProviders(carried.providers, input.loginReference).pipe(mapError2(() => unwritable));
|
|
2964
|
+
const globalConfig = input.carryOperatorFiles ? input.launch.globalConfig : undefined;
|
|
2965
|
+
const globalConfigFiles = globalConfig === undefined ? [] : yield* carriedGlobalConfig(globalConfig, input.loginReference).pipe(mapError2(() => unwritable));
|
|
2966
|
+
const files = [...input.launch.files, ...settings, ...providers, ...globalConfigFiles];
|
|
2967
|
+
const copies = carried?.copies ?? [];
|
|
2409
2968
|
const links = renewed === undefined ? [] : [renewed];
|
|
2410
|
-
|
|
2969
|
+
const globalConfigLinks = globalConfig?.links ?? [];
|
|
2970
|
+
if ([...files, ...copies, ...links, ...globalConfigLinks].some((file) => !isPathWithin2(path, input.configDir, file.path)))
|
|
2411
2971
|
return yield* unwritable;
|
|
2412
2972
|
for (const file of files) {
|
|
2413
2973
|
const { path } = file;
|
|
@@ -2417,14 +2977,17 @@ var writeHarnessFiles = (input) => gen(function* () {
|
|
|
2417
2977
|
if (yield* fs.exists(copy.source).pipe(orElseSucceed(() => false)))
|
|
2418
2978
|
yield* fs.makeDirectory(path.dirname(copy.path), { recursive: true }).pipe(andThen2(fs.copyFile(copy.source, copy.path)), mapError2(() => unwritable));
|
|
2419
2979
|
}
|
|
2980
|
+
for (const link of globalConfigLinks)
|
|
2981
|
+
yield* fs.makeDirectory(link.target, { recursive: true }).pipe(andThen2(fs.makeDirectory(path.dirname(link.path), { recursive: true })), andThen2(fs.symlink(link.target, link.path)), mapError2(() => unwritable));
|
|
2420
2982
|
if (input.carryOperatorFiles && input.launch.homeDirectory !== undefined)
|
|
2421
2983
|
yield* fs.makeDirectory(input.launch.homeDirectory, { recursive: true }).pipe(mapError2(() => unwritable));
|
|
2422
2984
|
if (renewed === undefined || login === undefined || !login.isPublished())
|
|
2423
2985
|
return;
|
|
2424
|
-
yield* fs.symlink(renewed.linksDirectory === true ? login.directory : login.file, renewed.path)
|
|
2986
|
+
yield* fs.makeDirectory(path.dirname(renewed.path), { recursive: true }).pipe(andThen2(fs.symlink(renewed.linksDirectory === true ? login.directory : login.file, renewed.path)), mapError2(() => unwritable));
|
|
2425
2987
|
const every = (millis, refresh) => forkScoped(forever(sleep(millis).pipe(andThen2(login.publish(refresh)), catch_((error) => logWarning("harness_login_not_renewed", error)))));
|
|
2426
2988
|
yield* every(loginRenewalMillis, true);
|
|
2427
|
-
|
|
2989
|
+
if (renewed.format !== "opencode")
|
|
2990
|
+
yield* every(loginCopyMillis, false);
|
|
2428
2991
|
const watching = makeUnsafe5();
|
|
2429
2992
|
yield* forkScoped(fs.watch(path.dirname(renewed.source), { onReady: () => doneUnsafe(watching, void_3) }).pipe(filter((event) => path.basename(event.path) === path.basename(renewed.source)), runForEach(() => login.publish(false)), catch_((error) => logWarning("harness_login_not_watched", error)), ensuring2(succeed4(watching, undefined))));
|
|
2430
2993
|
yield* _await(watching);
|
|
@@ -3067,8 +3630,7 @@ var transcriptSource = (adapter, place) => gen(function* () {
|
|
|
3067
3630
|
class SecretRegistryUnwritable extends TaggedError("SecretRegistryUnwritable") {
|
|
3068
3631
|
}
|
|
3069
3632
|
var runnerSecretOwner = "runner";
|
|
3070
|
-
var
|
|
3071
|
-
var holdsLoginByReference = (launch) => launch.renewedLogin?.format === "claude";
|
|
3633
|
+
var carriesLogin = (launch) => [launch.renewedLogin, launch.operatorFiles?.login, launch.operatorFiles?.providers, launch.globalConfig].some((file) => file !== undefined);
|
|
3072
3634
|
var stepSecretDirectory = (home, attemptId) => `${home}/.cache/kitman/step-secrets/${attemptId}`;
|
|
3073
3635
|
var requireSecretHosts = (secrets, destinations) => {
|
|
3074
3636
|
const unbound = Object.keys(secrets ?? {}).filter((name) => (destinations?.[name]?.hosts.length ?? 0) === 0);
|
|
@@ -3317,7 +3879,12 @@ var runAttempt = (request, options) => gen(function* () {
|
|
|
3317
3879
|
workspace,
|
|
3318
3880
|
configDir,
|
|
3319
3881
|
environment: { ...agent.secrets, ...launch.env, ...mcp.env },
|
|
3320
|
-
hosts:
|
|
3882
|
+
hosts: [
|
|
3883
|
+
...kitMcpHosts(kitSetup),
|
|
3884
|
+
...yield* carriedProviderHosts(launch),
|
|
3885
|
+
...yield* carriedLoginHosts(launch)
|
|
3886
|
+
],
|
|
3887
|
+
launch
|
|
3321
3888
|
});
|
|
3322
3889
|
const harnessArgv = [launch.binary, ...launch.args];
|
|
3323
3890
|
const sandboxed = gen(function* () {
|
|
@@ -3338,7 +3905,7 @@ var runAttempt = (request, options) => gen(function* () {
|
|
|
3338
3905
|
{ value, hosts: providerKeyHosts.get(name) ?? [] }
|
|
3339
3906
|
]))
|
|
3340
3907
|
};
|
|
3341
|
-
const holdsLogin =
|
|
3908
|
+
const holdsLogin = carriesLogin(launch);
|
|
3342
3909
|
const registry = Object.keys(initial).length === 0 && !holdsLogin ? undefined : yield* holdSecrets(initial);
|
|
3343
3910
|
const withSessions = sessions === undefined ? policy : {
|
|
3344
3911
|
...policy,
|
|
@@ -3422,15 +3989,17 @@ var runAttempt = (request, options) => gen(function* () {
|
|
|
3422
3989
|
launch,
|
|
3423
3990
|
configDir,
|
|
3424
3991
|
carryOperatorFiles: request.sandbox.backend !== "docker",
|
|
3425
|
-
...registry === undefined
|
|
3992
|
+
...registry === undefined ? undefined : {
|
|
3426
3993
|
loginReference: {
|
|
3427
|
-
reference:
|
|
3428
|
-
hold: (
|
|
3994
|
+
reference: (name) => secretReference(runnerSecretOwner, name),
|
|
3995
|
+
hold: (tokens) => forEach(Object.entries(tokens), ([reference, entry]) => registry.hold(reference, entry), {
|
|
3996
|
+
discard: true
|
|
3997
|
+
})
|
|
3429
3998
|
}
|
|
3430
3999
|
}
|
|
3431
4000
|
}), registry === undefined ? void_3 : watchSecretRegistry(registry, request, options.secretRevocationMs))));
|
|
3432
4001
|
if (adapter.id === "claude" && request.sandbox.backend !== "docker")
|
|
3433
|
-
yield* trustClaudeWorkspace(options.home, workspace).pipe(catch_((error) => logWarning("claude_trust_failed", error)));
|
|
4002
|
+
yield* trustClaudeWorkspace(launch.globalConfig === undefined ? options.home : (yield* Path).dirname(launch.globalConfig.path), workspace).pipe(catch_((error) => logWarning("claude_trust_failed", error)));
|
|
3434
4003
|
if (isFailure(command))
|
|
3435
4004
|
return failed(command.failure.reason, command.failure.summary);
|
|
3436
4005
|
const call = requester(options.core, yield* scope2);
|
|
@@ -3802,7 +4371,7 @@ var catchUpReport = (worktree, input) => gen(function* () {
|
|
|
3802
4371
|
const settled = input.automerged === undefined ? [] : (yield* names(input.automerged, input.merged)).filter((path) => !input.conflicted.includes(path));
|
|
3803
4372
|
const rewritten = [...new Set([...settled, ...yield* names(input.merged, input.head)])].sort();
|
|
3804
4373
|
const paths = [...new Set([...yield* names(before, input.from), ...yield* names(after, input.head)])].sort();
|
|
3805
|
-
const changed = yield*
|
|
4374
|
+
const changed = yield* filter3(paths.slice(0, catchUpPathLimit), (path) => map8(all3([ownDiff(before, input.from, path), ownDiff(after, input.head, path)]), ([was, is]) => was !== is), { concurrency: 8 });
|
|
3806
4375
|
const lists = [input.conflicted, rewritten, paths];
|
|
3807
4376
|
return {
|
|
3808
4377
|
from: input.from,
|
|
@@ -5419,7 +5988,7 @@ var agentStepSandboxPolicy = (work, apiUrl, runner) => ({
|
|
|
5419
5988
|
network: agentNetworkAllowlist({
|
|
5420
5989
|
apiUrl,
|
|
5421
5990
|
storageOrigin: work.storageOrigin,
|
|
5422
|
-
providerHosts: harnessAdapter(work.brief.harness)
|
|
5991
|
+
providerHosts: harnessNetworkHosts(harnessAdapter(work.brief.harness)),
|
|
5423
5992
|
...work.repoBinding === undefined ? undefined : { repoBindingHost: work.repoBinding.host },
|
|
5424
5993
|
...work.network === undefined ? undefined : { agent: work.network },
|
|
5425
5994
|
...work.hosts === undefined ? undefined : { allowed: work.hosts }
|
|
@@ -6465,7 +7034,7 @@ var regularFiles = (dir) => gen(function* () {
|
|
|
6465
7034
|
const fs = yield* FileSystem;
|
|
6466
7035
|
const path = yield* Path;
|
|
6467
7036
|
const real = yield* fs.realPath(dir);
|
|
6468
|
-
return yield*
|
|
7037
|
+
return yield* filter3((yield* fs.readDirectory(dir)).sort(), (name) => gen(function* () {
|
|
6469
7038
|
const entry = path.join(real, name);
|
|
6470
7039
|
return (yield* fs.realPath(entry)) === entry && (yield* fs.stat(entry)).type === "File";
|
|
6471
7040
|
}).pipe(orElseSucceed(() => false)));
|
|
@@ -6938,6 +7507,8 @@ export {
|
|
|
6938
7507
|
applyAgentEnvironmentMaterialization2 as applyAgentEnvironmentMaterialization,
|
|
6939
7508
|
applyAgentEnvironmentPlans,
|
|
6940
7509
|
assertHerdrRunnerCapability2 as assertHerdrRunnerCapability,
|
|
7510
|
+
carriedLoginHosts,
|
|
7511
|
+
carriedProviderHosts,
|
|
6941
7512
|
checkDockerAlias,
|
|
6942
7513
|
checkDockerClientConfig,
|
|
6943
7514
|
checkDockerDaemonArgs,
|
|
@@ -6971,6 +7542,7 @@ export {
|
|
|
6971
7542
|
halfCloseListener,
|
|
6972
7543
|
harnessAdapter,
|
|
6973
7544
|
harnessConfigUnwritable,
|
|
7545
|
+
harnessNetworkHosts,
|
|
6974
7546
|
harnessesInSrt,
|
|
6975
7547
|
harnessesUnsupportedInSrt2 as harnessesUnsupportedInSrt,
|
|
6976
7548
|
herdrAttemptLeased,
|