orizu 0.5.26 → 0.5.28
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/README.md +19 -0
- package/dist/artifacts-git-runtime.d.ts +34 -0
- package/dist/artifacts-git-runtime.d.ts.map +1 -0
- package/dist/artifacts-git-runtime.js +312 -0
- package/dist/cloudflare-artifacts-git-remote.d.ts +5 -0
- package/dist/cloudflare-artifacts-git-remote.d.ts.map +1 -0
- package/dist/cloudflare-artifacts-git-remote.js +21 -0
- package/dist/dataset-transfer-download.d.ts +2 -0
- package/dist/dataset-transfer-download.d.ts.map +1 -0
- package/dist/dataset-transfer-download.js +66 -0
- package/dist/dataset-transfer-policy.d.ts +2 -0
- package/dist/dataset-transfer-policy.d.ts.map +1 -0
- package/dist/dataset-transfer-policy.js +8 -0
- package/dist/dataset-transfer-upload.d.ts +42 -0
- package/dist/dataset-transfer-upload.d.ts.map +1 -0
- package/dist/dataset-transfer-upload.js +110 -0
- package/dist/git-credential.d.ts.map +1 -1
- package/dist/git-credential.js +1 -1
- package/dist/git-recovery-environment.d.ts +1 -0
- package/dist/git-recovery-environment.d.ts.map +1 -1
- package/dist/git-recovery-environment.js +1 -1
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +44 -11
- package/dist/hosted-boot.d.ts +75 -2
- package/dist/hosted-boot.d.ts.map +1 -1
- package/dist/hosted-boot.js +585 -102
- package/dist/hosted-bootstrap.d.ts +2 -0
- package/dist/hosted-bootstrap.d.ts.map +1 -1
- package/dist/hosted-bootstrap.js +12 -3
- package/dist/hosted-harness-opencode.d.ts +8 -9
- package/dist/hosted-harness-opencode.d.ts.map +1 -1
- package/dist/hosted-harness-opencode.js +126 -24
- package/dist/hosted-harness.d.ts +3 -0
- package/dist/hosted-harness.d.ts.map +1 -1
- package/dist/hosted-harness.js +4 -1
- package/dist/hosted-harvest.d.ts +30 -9
- package/dist/hosted-harvest.d.ts.map +1 -1
- package/dist/hosted-harvest.js +222 -28
- package/dist/hosted-loop-lifecycle.d.ts +15 -3
- package/dist/hosted-loop-lifecycle.d.ts.map +1 -1
- package/dist/hosted-loop-lifecycle.js +6 -4
- package/dist/hosted-loop.d.ts +47 -7
- package/dist/hosted-loop.d.ts.map +1 -1
- package/dist/hosted-loop.js +310 -64
- package/dist/hosted-question-limits.d.ts +7 -0
- package/dist/hosted-question-limits.d.ts.map +1 -0
- package/dist/hosted-question-limits.js +6 -0
- package/dist/hosted-question.d.ts +27 -0
- package/dist/hosted-question.d.ts.map +1 -0
- package/dist/hosted-question.js +118 -0
- package/dist/hosted-run-event-sink.d.ts +10 -5
- package/dist/hosted-run-event-sink.d.ts.map +1 -1
- package/dist/hosted-run-event-sink.js +12 -8
- package/dist/hosted-runtime-assets.d.ts +16 -7
- package/dist/hosted-runtime-assets.d.ts.map +1 -1
- package/dist/hosted-runtime-assets.js +40 -12
- package/dist/hosted-session-cli.d.ts.map +1 -1
- package/dist/hosted-session-cli.js +10 -19
- package/dist/http.d.ts +1 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +113 -92
- package/dist/instruction-set-gepa-launch.d.ts +1 -1
- package/dist/instruction-set-gepa-launch.d.ts.map +1 -1
- package/dist/instruction-set-gepa-launch.js +5 -3
- package/dist/instruction-set-loader.d.ts.map +1 -1
- package/dist/instruction-set-loader.js +63 -2
- package/dist/instruction-set-lock/index.d.ts +51 -0
- package/dist/instruction-set-lock/index.d.ts.map +1 -0
- package/dist/instruction-set-lock/index.js +459 -0
- package/dist/instruction-set-lock/schema.v1.d.ts +136 -0
- package/dist/instruction-set-lock/schema.v1.d.ts.map +1 -0
- package/dist/instruction-set-lock/schema.v1.js +155 -0
- package/dist/instruction-set-provenance.d.ts +26 -0
- package/dist/instruction-set-provenance.d.ts.map +1 -0
- package/dist/instruction-set-provenance.js +68 -0
- package/dist/instruction-set-sync/helpers.d.ts +22 -0
- package/dist/instruction-set-sync/helpers.d.ts.map +1 -0
- package/dist/instruction-set-sync/helpers.js +677 -0
- package/dist/instruction-set-sync/index.d.ts +60 -0
- package/dist/instruction-set-sync/index.d.ts.map +1 -0
- package/dist/instruction-set-sync/index.js +689 -0
- package/dist/instruction-set-update/index.d.ts +42 -0
- package/dist/instruction-set-update/index.d.ts.map +1 -0
- package/dist/instruction-set-update/index.js +445 -0
- package/dist/instruction-set-verify/index.d.ts +27 -0
- package/dist/instruction-set-verify/index.d.ts.map +1 -0
- package/dist/instruction-set-verify/index.js +865 -0
- package/dist/instruction-sets-cli.d.ts +1 -4
- package/dist/instruction-sets-cli.d.ts.map +1 -1
- package/dist/instruction-sets-cli.js +220 -109
- package/dist/model-config-fields.d.ts +35 -0
- package/dist/model-config-fields.d.ts.map +1 -0
- package/dist/model-config-fields.js +28 -0
- package/dist/optimizations-list-cli.d.ts.map +1 -1
- package/dist/optimizations-list-cli.js +7 -4
- package/dist/score-format.d.ts +2 -0
- package/dist/score-format.d.ts.map +1 -0
- package/dist/score-format.js +18 -0
- package/dist/workbench-repo-contract.d.ts +65 -0
- package/dist/workbench-repo-contract.d.ts.map +1 -0
- package/dist/workbench-repo-contract.js +250 -0
- package/dist/workspace-bootstrap-job.d.ts +45 -0
- package/dist/workspace-bootstrap-job.d.ts.map +1 -0
- package/dist/workspace-bootstrap-job.js +431 -0
- package/dist/workspace-bootstrap-seed.d.ts +74 -0
- package/dist/workspace-bootstrap-seed.d.ts.map +1 -0
- package/dist/workspace-bootstrap-seed.js +209 -0
- package/package.json +4 -3
- package/src/artifacts-git-runtime.ts +360 -0
- package/src/cloudflare-artifacts-git-remote.ts +24 -0
- package/src/dataset-transfer-download.ts +61 -0
- package/src/dataset-transfer-policy.ts +8 -0
- package/src/dataset-transfer-upload.ts +145 -0
- package/src/git-credential.ts +1 -2
- package/src/git-recovery-environment.ts +1 -1
- package/src/help.ts +44 -11
- package/src/hosted-boot.ts +644 -109
- package/src/hosted-bootstrap.ts +14 -3
- package/src/hosted-harness-opencode.ts +130 -28
- package/src/hosted-harness.ts +4 -1
- package/src/hosted-harvest.ts +258 -33
- package/src/hosted-loop-lifecycle.ts +19 -5
- package/src/hosted-loop.ts +340 -68
- package/src/hosted-question-limits.ts +6 -0
- package/src/hosted-question.ts +145 -0
- package/src/hosted-run-event-sink.ts +24 -12
- package/src/hosted-runtime-assets.ts +51 -11
- package/src/hosted-session-cli.ts +10 -24
- package/src/http.ts +10 -4
- package/src/index.ts +108 -134
- package/src/instruction-set-gepa-launch.ts +4 -4
- package/src/instruction-set-loader.ts +53 -2
- package/src/instruction-set-lock/index.ts +561 -0
- package/src/instruction-set-lock/schema.v1.json +141 -0
- package/src/instruction-set-lock/schema.v1.ts +155 -0
- package/src/instruction-set-provenance.ts +89 -0
- package/src/instruction-set-sync/helpers.ts +707 -0
- package/src/instruction-set-sync/index.ts +791 -0
- package/src/instruction-set-update/index.ts +488 -0
- package/src/instruction-set-verify/index.ts +1067 -0
- package/src/instruction-sets-cli.ts +226 -114
- package/src/model-config-fields.ts +31 -0
- package/src/optimizations-list-cli.ts +7 -4
- package/src/score-format.ts +16 -0
- package/src/workbench-repo-contract.ts +314 -0
- package/src/workspace-bootstrap-job.ts +611 -0
- package/src/workspace-bootstrap-seed.ts +350 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/instruction_set_loader.py +46 -2
- package/vendor/skills/orizu/SKILL.md +4 -2
- package/vendor/skills/orizu/flows/promote.md +4 -0
- package/vendor/skills/orizu/references/assess-and-plan.md +1 -1
- package/vendor/skills/orizu/references/authority-map.md +1 -1
- package/vendor/skills/orizu/references/cli-reference.md +151 -35
- package/vendor/skills/orizu/references/instructions-after-prompts.md +3 -3
- package/vendor/skills/orizu/references/migrate-existing-gepa-setup.md +5 -6
- package/vendor/skills/orizu/references/migrate-hand-rolled-instruction-layout.md +252 -0
- package/vendor/skills/orizu/references/optimization-reports.md +5 -4
- package/vendor/skills/orizu/references/optimization-with-gepa.md +1 -1
- package/vendor/skills/orizu/references/orizu-in-your-codebase.md +195 -0
- package/vendor/skills/orizu/references/primer.md +4 -2
- package/vendor/skills/orizu/references/prompt-control-plane.md +33 -29
- package/vendor/skills/orizu/references/vocabulary.md +1 -1
package/src/hosted-bootstrap.ts
CHANGED
|
@@ -208,6 +208,8 @@ export interface HostedBootstrapResult {
|
|
|
208
208
|
steps: HostedBootstrapStep[]
|
|
209
209
|
events: readonly AppendedRunEvent[]
|
|
210
210
|
paths: HostedRuntimePaths
|
|
211
|
+
/** Bootstrap-selected helper, carried out-of-repo to checkpoint transport. */
|
|
212
|
+
credentialHelper: string
|
|
211
213
|
/** Set on the failure path: the residue sweep result after teardown. */
|
|
212
214
|
sweep: { clean: boolean; findings: HygieneFinding[] } | null
|
|
213
215
|
failure: { step: string; error: string } | null
|
|
@@ -478,7 +480,10 @@ export async function bootstrapHostedSandbox(opts: HostedBootstrapOptions): Prom
|
|
|
478
480
|
if (opts.deferSetupHook) {
|
|
479
481
|
record('setup_hook_deferred', true, 'deferred to loop (runs after egress canary)')
|
|
480
482
|
await sink.append('setup_hook_deferred', { reason: 'egress canary must pass before customer setup.sh runs' })
|
|
481
|
-
return {
|
|
483
|
+
return {
|
|
484
|
+
ok: true, steps, events: sink.recorded, paths,
|
|
485
|
+
credentialHelper: helperValue, sweep: null, failure: null,
|
|
486
|
+
}
|
|
482
487
|
}
|
|
483
488
|
const hookRel = `${workspaceDir}/${SETUP_HOOK_RELATIVE_PATH}`
|
|
484
489
|
if (await session.fileExists(hookRel)) {
|
|
@@ -495,14 +500,20 @@ export async function bootstrapHostedSandbox(opts: HostedBootstrapOptions): Prom
|
|
|
495
500
|
await sink.append('setup_hook_skipped', { reason: 'no .orizu/setup.sh' })
|
|
496
501
|
}
|
|
497
502
|
|
|
498
|
-
return {
|
|
503
|
+
return {
|
|
504
|
+
ok: true, steps, events: sink.recorded, paths,
|
|
505
|
+
credentialHelper: helperValue, sweep: null, failure: null,
|
|
506
|
+
}
|
|
499
507
|
} catch (error) {
|
|
500
508
|
const message = error instanceof Error ? error.message : String(error)
|
|
501
509
|
record(currentStep, false, message)
|
|
502
510
|
// Record the failure (redacted), then tear down + prove no residue remains.
|
|
503
511
|
await safeAppend(sink, 'bootstrap_failed', { step: currentStep, error: message })
|
|
504
512
|
const sweep = await teardownHostedSandbox({ session, paths, bearer: opts.bearer, workspaceDir })
|
|
505
|
-
return {
|
|
513
|
+
return {
|
|
514
|
+
ok: false, steps, events: sink.recorded, paths, credentialHelper: helperValue,
|
|
515
|
+
sweep, failure: { step: currentStep, error: message },
|
|
516
|
+
}
|
|
506
517
|
}
|
|
507
518
|
}
|
|
508
519
|
|
|
@@ -331,6 +331,12 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
331
331
|
// Set true by the public stop(); makes the next idle terminal resolve as a
|
|
332
332
|
// cancellation rather than a success (P2-2).
|
|
333
333
|
let stopRequested = false
|
|
334
|
+
let stopRequest: Promise<void> | null = null
|
|
335
|
+
let promptSubmissionPending = false
|
|
336
|
+
let promptSubmissionSettled: Promise<void> | null = null
|
|
337
|
+
let resolvePromptSubmission: (() => void) | null = null
|
|
338
|
+
let postAcceptanceAbortGeneration = -1
|
|
339
|
+
let promptGeneration = 0
|
|
334
340
|
// Last title actually forwarded, deduped across the whole harness lifetime so
|
|
335
341
|
// a repeated identical title is emitted once (P3-6).
|
|
336
342
|
let lastForwardedTitle: string | null = null
|
|
@@ -379,14 +385,51 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
379
385
|
}
|
|
380
386
|
}
|
|
381
387
|
|
|
382
|
-
async function requestStop(): Promise<void> {
|
|
388
|
+
async function requestStop(options: { force?: boolean } = {}): Promise<void> {
|
|
383
389
|
if (!opencodeSessionId) return
|
|
390
|
+
if (
|
|
391
|
+
promptSubmissionPending &&
|
|
392
|
+
promptSubmissionSettled &&
|
|
393
|
+
postAcceptanceAbortGeneration !== promptGeneration
|
|
394
|
+
) {
|
|
395
|
+
const racedGeneration = promptGeneration
|
|
396
|
+
const settlement = promptSubmissionSettled
|
|
397
|
+
postAcceptanceAbortGeneration = racedGeneration
|
|
398
|
+
// The stream consumer may close this generator as soon as its signal
|
|
399
|
+
// aborts. Keep the post-acceptance abort independent of generator
|
|
400
|
+
// continuation so an accepted prompt cannot escape cancellation.
|
|
401
|
+
void settlement.then(() => requestStop({ force: true }))
|
|
402
|
+
}
|
|
403
|
+
// Prompt signal + the hosted-loop stop() belt normally share one successful
|
|
404
|
+
// request. A failed request is never memoized, and prompt acknowledgement
|
|
405
|
+
// can force a post-acceptance abort when an earlier abort raced ahead of it.
|
|
406
|
+
if (stopRequest && !options.force) {
|
|
407
|
+
const inFlight = stopRequest
|
|
408
|
+
try {
|
|
409
|
+
await inFlight
|
|
410
|
+
return
|
|
411
|
+
} catch {
|
|
412
|
+
if (stopRequest === inFlight) stopRequest = null
|
|
413
|
+
// The owner of the failed request handles its own best-effort result.
|
|
414
|
+
// This overlapping caller owns the one follow-up acknowledgement try;
|
|
415
|
+
// it must never inherit the rejected memo as a fatal prompt error.
|
|
416
|
+
return requestStop(options)
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const request = (async () => {
|
|
420
|
+
const response = await timedFetch(
|
|
421
|
+
`${base}/session/${encodeURIComponent(opencodeSessionId!)}/abort`,
|
|
422
|
+
{ method: 'POST' }
|
|
423
|
+
)
|
|
424
|
+
if (!response.ok) throw new Error(`OpenCode abort failed (${response.status})`)
|
|
425
|
+
})()
|
|
426
|
+
stopRequest = request
|
|
384
427
|
try {
|
|
385
|
-
await
|
|
386
|
-
method: 'POST',
|
|
387
|
-
})
|
|
428
|
+
await request
|
|
388
429
|
} catch {
|
|
389
|
-
|
|
430
|
+
if (stopRequest === request) stopRequest = null
|
|
431
|
+
// best-effort: stream teardown still settles this attempt, while a later
|
|
432
|
+
// stop can retry because the failed request no longer owns the memo.
|
|
390
433
|
}
|
|
391
434
|
}
|
|
392
435
|
|
|
@@ -454,9 +497,14 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
454
497
|
async *runPrompt(prompt: HarnessPrompt, signal: AbortSignal): AsyncIterable<HarnessEvent> {
|
|
455
498
|
if (!opencodeSessionId) opencodeSessionId = await createSession()
|
|
456
499
|
const sessionId = opencodeSessionId
|
|
500
|
+
promptGeneration += 1
|
|
457
501
|
|
|
458
|
-
// Per-prompt state: a fresh stop
|
|
459
|
-
|
|
502
|
+
// Per-prompt state: a fresh stop generation unless a human interrupt was
|
|
503
|
+
// already delivered before this generator began iterating.
|
|
504
|
+
if (!signal.aborted) {
|
|
505
|
+
stopRequested = false
|
|
506
|
+
stopRequest = null
|
|
507
|
+
}
|
|
460
508
|
let compactionOccurred = false
|
|
461
509
|
const promptStart = now()
|
|
462
510
|
|
|
@@ -469,6 +517,20 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
469
517
|
}
|
|
470
518
|
}
|
|
471
519
|
|
|
520
|
+
// A durable interrupt can predate generator iteration. Do not submit a
|
|
521
|
+
// prompt merely to abort it; report the prompt-scoped cancellation after
|
|
522
|
+
// the stop belt has had a chance to settle.
|
|
523
|
+
if (signal.aborted) {
|
|
524
|
+
await requestStop()
|
|
525
|
+
yield {
|
|
526
|
+
kind: 'execution_complete',
|
|
527
|
+
messageId: prompt.messageId,
|
|
528
|
+
critical: true,
|
|
529
|
+
payload: { success: false, aborted: true },
|
|
530
|
+
}
|
|
531
|
+
return
|
|
532
|
+
}
|
|
533
|
+
|
|
472
534
|
const opencodeMessageId = ascendingId('msg')
|
|
473
535
|
const requestBody = buildPromptRequestBody(
|
|
474
536
|
prompt.content,
|
|
@@ -542,6 +604,20 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
542
604
|
return events
|
|
543
605
|
}
|
|
544
606
|
|
|
607
|
+
// The vulnerable submission window begins before /event is opened and
|
|
608
|
+
// ends only when prompt_async settles. A stop anywhere in this window
|
|
609
|
+
// schedules an independent post-acceptance abort.
|
|
610
|
+
promptSubmissionPending = true
|
|
611
|
+
promptSubmissionSettled = new Promise<void>(resolve => {
|
|
612
|
+
resolvePromptSubmission = resolve
|
|
613
|
+
})
|
|
614
|
+
const settlePromptSubmission = (): void => {
|
|
615
|
+
promptSubmissionPending = false
|
|
616
|
+
resolvePromptSubmission?.()
|
|
617
|
+
resolvePromptSubmission = null
|
|
618
|
+
promptSubmissionSettled = null
|
|
619
|
+
}
|
|
620
|
+
|
|
545
621
|
let sseResponse: Response
|
|
546
622
|
try {
|
|
547
623
|
sseResponse = await fetchImpl(`${base}/event`, {
|
|
@@ -549,10 +625,22 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
549
625
|
signal,
|
|
550
626
|
})
|
|
551
627
|
} catch (error) {
|
|
552
|
-
|
|
628
|
+
settlePromptSubmission()
|
|
629
|
+
if (signal.aborted) {
|
|
630
|
+
await requestStop()
|
|
631
|
+
yield {
|
|
632
|
+
kind: 'execution_complete',
|
|
633
|
+
messageId: prompt.messageId,
|
|
634
|
+
critical: true,
|
|
635
|
+
payload: { success: false, aborted: true },
|
|
636
|
+
}
|
|
637
|
+
} else {
|
|
638
|
+
yield errorEvent(prompt.messageId, error)
|
|
639
|
+
}
|
|
553
640
|
return
|
|
554
641
|
}
|
|
555
642
|
if (!sseResponse.ok || !sseResponse.body) {
|
|
643
|
+
settlePromptSubmission()
|
|
556
644
|
// Cancel the body on the failure path too — a non-2xx response can still
|
|
557
645
|
// carry an (unconsumed) body that would otherwise leak (P3-7).
|
|
558
646
|
await cancelBody(sseResponse.body)
|
|
@@ -565,18 +653,22 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
565
653
|
let errorText: string | null = null
|
|
566
654
|
let terminalYielded = false
|
|
567
655
|
try {
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
656
|
+
let promptRes: Response
|
|
657
|
+
try {
|
|
658
|
+
promptRes = await timedFetch(
|
|
659
|
+
`${base}/session/${encodeURIComponent(sessionId)}/prompt_async`,
|
|
660
|
+
{
|
|
661
|
+
method: 'POST',
|
|
662
|
+
headers: { 'Content-Type': 'application/json' },
|
|
663
|
+
body: JSON.stringify(requestBody),
|
|
664
|
+
}
|
|
665
|
+
)
|
|
666
|
+
} finally {
|
|
667
|
+
settlePromptSubmission()
|
|
668
|
+
}
|
|
576
669
|
if (promptRes.status !== 200 && promptRes.status !== 204) {
|
|
577
670
|
throw new Error(`Async prompt failed (${promptRes.status})`)
|
|
578
671
|
}
|
|
579
|
-
|
|
580
672
|
for await (const event of parseSseEvents(sseBody, signal, inactivityMs)) {
|
|
581
673
|
// Wall-clock max-duration guard (P3-1): a stream that stays busy (or
|
|
582
674
|
// heartbeats) forever never trips the inactivity deadline, so bound it
|
|
@@ -747,16 +839,23 @@ export function createOpenCodeHarness(options: OpenCodeHarnessOptions): AgentHar
|
|
|
747
839
|
},
|
|
748
840
|
|
|
749
841
|
async stop(): Promise<void> {
|
|
750
|
-
// Mark intent so the resulting idle terminal is reported as cancelled,
|
|
751
|
-
// succeeded (P2-2), then best-effort ask OpenCode to abort.
|
|
842
|
+
// Mark intent so the resulting idle terminal is reported as cancelled,
|
|
843
|
+
// not succeeded (P2-2), then best-effort ask OpenCode to abort.
|
|
752
844
|
stopRequested = true
|
|
753
845
|
await requestStop()
|
|
754
846
|
},
|
|
755
847
|
|
|
756
848
|
async shutdown(): Promise<void> {
|
|
849
|
+
if (process.env.NODE_ENV === 'test' &&
|
|
850
|
+
process.env.ORIZU_HOSTED_TEST_HARNESS_SHUTDOWN_THROWS === '1') {
|
|
851
|
+
throw new Error('fixture harness shutdown failed')
|
|
852
|
+
}
|
|
757
853
|
opencodeSessionId = null
|
|
758
854
|
readyEmitted = false
|
|
759
855
|
stopRequested = false
|
|
856
|
+
stopRequest = null
|
|
857
|
+
promptGeneration = 0
|
|
858
|
+
postAcceptanceAbortGeneration = -1
|
|
760
859
|
},
|
|
761
860
|
}
|
|
762
861
|
}
|
|
@@ -971,15 +1070,12 @@ export interface OpenCodeConfigOptions {
|
|
|
971
1070
|
}
|
|
972
1071
|
|
|
973
1072
|
/**
|
|
974
|
-
* Tools
|
|
975
|
-
*
|
|
976
|
-
*
|
|
977
|
-
*
|
|
978
|
-
*
|
|
979
|
-
*
|
|
980
|
-
* to it as a tool error) so it proceeds autonomously per the standing preamble
|
|
981
|
-
* (HOSTED_TASK_PREAMBLE), instead of blocking the run forever. This is the
|
|
982
|
-
* documented fallback path in ALI-1037 (answer-externally is not cleanly possible).
|
|
1073
|
+
* Tools denied for CLI-origin headless runs (ALI-1037). OpenCode 1.14.41 removes
|
|
1074
|
+
* a tool from the model toolset when its permission rule is `deny` on `*`; it does
|
|
1075
|
+
* not expose the tool and report a denial result. Hosted-web therefore overrides
|
|
1076
|
+
* `question` to `allow`, intercepts its measured running part, and quiesces the
|
|
1077
|
+
* turn while waiting for the human. CLI-origin runs retain this deny list because
|
|
1078
|
+
* no human reply flow exists there.
|
|
983
1079
|
*/
|
|
984
1080
|
export const HEADLESS_DENIED_TOOLS = ['question'] as const
|
|
985
1081
|
|
|
@@ -991,6 +1087,12 @@ export function defaultHeadlessPermission(): Record<string, unknown> {
|
|
|
991
1087
|
return permission
|
|
992
1088
|
}
|
|
993
1089
|
|
|
1090
|
+
/** Select the OpenCode permission map for the session's human-input surface. */
|
|
1091
|
+
export function permissionForOrigin(origin?: 'hosted-web' | 'cli'): Record<string, unknown> {
|
|
1092
|
+
if (origin === 'hosted-web') return { ...defaultHeadlessPermission(), question: 'allow' }
|
|
1093
|
+
return defaultHeadlessPermission()
|
|
1094
|
+
}
|
|
1095
|
+
|
|
994
1096
|
/**
|
|
995
1097
|
* Build the `OPENCODE_CONFIG_CONTENT` payload OpenCode reads at boot (mirrors
|
|
996
1098
|
* OpenInspect's `start_opencode`). Kept pure so the launch command and the
|
package/src/hosted-harness.ts
CHANGED
|
@@ -81,13 +81,16 @@ export const HARNESS_EVENT_KINDS = {
|
|
|
81
81
|
egress_allowed: 'egress_allowed',
|
|
82
82
|
// Durability + headless (ALI-1036 / ALI-1037). NOT produced by a harness — the
|
|
83
83
|
// in-sandbox loop emits these through the SAME single-writer run-event sink:
|
|
84
|
-
// the end-of-run auto-harvest result (
|
|
84
|
+
// the end-of-run auto-harvest result (persisted/none/not-inspected/failed)
|
|
85
85
|
// and the headless question auto-handling record (question_auto_answered). They
|
|
86
86
|
// are ordinary structural events (never terminal), appended like any other.
|
|
87
87
|
work_persisted: 'work_persisted',
|
|
88
88
|
work_none: 'work_none',
|
|
89
|
+
work_not_inspected: 'work_not_inspected',
|
|
89
90
|
work_persist_failed: 'work_persist_failed',
|
|
90
91
|
question_auto_answered: 'question_auto_answered',
|
|
92
|
+
question_pending: 'question_pending',
|
|
93
|
+
question_invalid: 'question_invalid',
|
|
91
94
|
error: 'error',
|
|
92
95
|
execution_complete: 'execution_complete',
|
|
93
96
|
} as const
|