@aspectlylabs/mikka 0.0.201 → 0.0.203
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/capture-copy.mjs +26 -0
- package/cli.js +437 -245
- package/client.js +16 -6
- package/http-link.js +706 -692
- package/login.js +61 -53
- package/main.js +385 -197
- package/mikka-release-manifest.json +25 -20
- package/mikka.js +437 -245
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
- package/paths.js +5 -4
- package/sbom.cdx.json +7 -7
package/http-link.js
CHANGED
|
@@ -2498,8 +2498,20 @@ function matchesRunSandboxDomain(request, domains) {
|
|
|
2498
2498
|
});
|
|
2499
2499
|
}
|
|
2500
2500
|
|
|
2501
|
+
// ../protocol/src/mailbox.ts
|
|
2502
|
+
import { z as z4 } from "zod";
|
|
2503
|
+
var mailboxSend = z4.object({ to: z4.uuid(), key: z4.uuid().describe("Stable idempotency key; reuse only to retry this exact envelope."), text: z4.string().trim().min(1).max(4e3), replyTo: z4.uuid().optional() }).strict();
|
|
2504
|
+
var mailboxAck = z4.object({ ids: z4.array(z4.uuid()).max(50) }).strict();
|
|
2505
|
+
var mailboxInputs = {
|
|
2506
|
+
mailbox_recipients: z4.object({}).strict(),
|
|
2507
|
+
mailbox_send: mailboxSend,
|
|
2508
|
+
mailbox_inbox: z4.object({}).strict(),
|
|
2509
|
+
mailbox_ack: mailboxAck,
|
|
2510
|
+
mailbox_sent: z4.object({}).strict()
|
|
2511
|
+
};
|
|
2512
|
+
|
|
2501
2513
|
// src/agents/tool-approval-policy.ts
|
|
2502
|
-
function toolApprovalDecision(request, policy, worktree, apps = [], runHosts = []) {
|
|
2514
|
+
function toolApprovalDecision(request, policy, worktree, apps = [], runHosts = [], mailboxEnabled = false) {
|
|
2503
2515
|
if (request.method === "sandbox/network" && policy) {
|
|
2504
2516
|
const value = request.input;
|
|
2505
2517
|
if (!value || typeof value.host !== "string" || /[*/:]/.test(value.host) || !networkDomainSchema.safeParse(value.host).success || !Number.isInteger(value.port) || Number(value.port) < 1 || Number(value.port) > 65535) return "deny";
|
|
@@ -2512,6 +2524,7 @@ function toolApprovalDecision(request, policy, worktree, apps = [], runHosts = [
|
|
|
2512
2524
|
return policy.readOnly || !policy.permissions.computer_use || policy.permissions.computer_use === "deny" ? "deny" : "allow";
|
|
2513
2525
|
}
|
|
2514
2526
|
if (["submit", "request_help", "ask_human", "report_blocked", "submit_capture"].some((name) => tool === `mcp__mikka__${name}`)) return "allow";
|
|
2527
|
+
if (mailboxEnabled && Object.keys(mailboxInputs).some((name) => tool === `mcp__mikka_mailbox__${name}`)) return "allow";
|
|
2515
2528
|
if (tool === "Bash" || tool === "PowerShell") return rawCliShellAvailable(policy) ? "allow" : "unavailable";
|
|
2516
2529
|
if (apps.some((name) => tool.startsWith(`mcp__${name}__`) && tool.length > `mcp__${name}__`.length)) return "allow";
|
|
2517
2530
|
if (tool === "WebFetch" || tool === "WebSearch") return policy.permissions.network;
|
|
@@ -2546,34 +2559,34 @@ function runApps(mcp) {
|
|
|
2546
2559
|
}
|
|
2547
2560
|
|
|
2548
2561
|
// ../protocol/src/skill.ts
|
|
2549
|
-
import { z as
|
|
2562
|
+
import { z as z6 } from "zod";
|
|
2550
2563
|
|
|
2551
2564
|
// ../protocol/src/skill-artifact.ts
|
|
2552
|
-
import { z as
|
|
2565
|
+
import { z as z5 } from "zod";
|
|
2553
2566
|
var SKILL_ARTIFACT_HEADER = "x-mikka-skill-artifacts";
|
|
2554
2567
|
var TEAM_SKILL_HEADER = "x-mikka-team-skills";
|
|
2555
|
-
var skillArtifactRefSchema =
|
|
2556
|
-
schemaVersion:
|
|
2557
|
-
registryId:
|
|
2558
|
-
skillId:
|
|
2559
|
-
versionId:
|
|
2560
|
-
format:
|
|
2561
|
-
sha256:
|
|
2568
|
+
var skillArtifactRefSchema = z5.object({
|
|
2569
|
+
schemaVersion: z5.literal(1),
|
|
2570
|
+
registryId: z5.enum(["mikka-builtin", "mikka-team"]),
|
|
2571
|
+
skillId: z5.uuid(),
|
|
2572
|
+
versionId: z5.uuid(),
|
|
2573
|
+
format: z5.literal("single-skill-md-v1"),
|
|
2574
|
+
sha256: z5.string().regex(/^[a-f0-9]{64}$/)
|
|
2562
2575
|
}).strict();
|
|
2563
|
-
var skillAssignmentReceiptSchema =
|
|
2564
|
-
id:
|
|
2565
|
-
runId:
|
|
2566
|
-
issueId:
|
|
2567
|
-
agentId:
|
|
2568
|
-
repoId:
|
|
2569
|
-
deviceId:
|
|
2570
|
-
leaseExpiresAt:
|
|
2571
|
-
assignedAt:
|
|
2576
|
+
var skillAssignmentReceiptSchema = z5.object({
|
|
2577
|
+
id: z5.uuid(),
|
|
2578
|
+
runId: z5.uuid(),
|
|
2579
|
+
issueId: z5.uuid(),
|
|
2580
|
+
agentId: z5.uuid(),
|
|
2581
|
+
repoId: z5.uuid(),
|
|
2582
|
+
deviceId: z5.uuid(),
|
|
2583
|
+
leaseExpiresAt: z5.iso.datetime(),
|
|
2584
|
+
assignedAt: z5.iso.datetime(),
|
|
2572
2585
|
artifact: skillArtifactRefSchema
|
|
2573
2586
|
}).strict();
|
|
2574
|
-
var skillReceiptRevalidationSchema =
|
|
2587
|
+
var skillReceiptRevalidationSchema = z5.object({
|
|
2575
2588
|
skillReceipt: skillAssignmentReceiptSchema,
|
|
2576
|
-
leaseExpiresAt:
|
|
2589
|
+
leaseExpiresAt: z5.iso.datetime()
|
|
2577
2590
|
}).strict();
|
|
2578
2591
|
|
|
2579
2592
|
// ../protocol/src/skill.ts
|
|
@@ -2584,39 +2597,39 @@ var MAX_SKILL_INSTRUCTIONS_LENGTH = 2e4;
|
|
|
2584
2597
|
var MAX_SKILL_FILES = 20;
|
|
2585
2598
|
var MAX_SKILL_FILE_PATH_LENGTH = 200;
|
|
2586
2599
|
var MAX_SKILL_FILE_CONTENT_LENGTH = 1e5;
|
|
2587
|
-
var skillFilePathSchema =
|
|
2600
|
+
var skillFilePathSchema = z6.string().min(1).max(MAX_SKILL_FILE_PATH_LENGTH).refine(
|
|
2588
2601
|
(path) => !path.startsWith("/") && !path.includes("\\") && !path.split("/").some((segment) => segment === ".." || segment === ""),
|
|
2589
2602
|
{ message: "A skill file path must be relative and stay inside the skill." }
|
|
2590
2603
|
);
|
|
2591
|
-
var skillFileSchema =
|
|
2604
|
+
var skillFileSchema = z6.object({
|
|
2592
2605
|
path: skillFilePathSchema,
|
|
2593
|
-
content:
|
|
2606
|
+
content: z6.string().max(MAX_SKILL_FILE_CONTENT_LENGTH)
|
|
2594
2607
|
});
|
|
2595
|
-
var skillFilesSchema =
|
|
2596
|
-
var skillNameSchema =
|
|
2597
|
-
var skillDescriptionSchema =
|
|
2598
|
-
var skillInstructionsSchema =
|
|
2599
|
-
var runSkillSchema =
|
|
2600
|
-
id:
|
|
2608
|
+
var skillFilesSchema = z6.array(skillFileSchema).max(MAX_SKILL_FILES);
|
|
2609
|
+
var skillNameSchema = z6.string().trim().min(1).max(MAX_SKILL_NAME_LENGTH);
|
|
2610
|
+
var skillDescriptionSchema = z6.string().trim().max(MAX_SKILL_DESCRIPTION_LENGTH);
|
|
2611
|
+
var skillInstructionsSchema = z6.string().trim().min(1).max(MAX_SKILL_INSTRUCTIONS_LENGTH);
|
|
2612
|
+
var runSkillSchema = z6.object({
|
|
2613
|
+
id: z6.uuid(),
|
|
2601
2614
|
name: skillNameSchema,
|
|
2602
|
-
description:
|
|
2615
|
+
description: z6.string().nullable(),
|
|
2603
2616
|
instructions: skillInstructionsSchema,
|
|
2604
2617
|
files: skillFilesSchema
|
|
2605
2618
|
});
|
|
2606
|
-
var runSkillRefSchema =
|
|
2607
|
-
id:
|
|
2619
|
+
var runSkillRefSchema = z6.object({
|
|
2620
|
+
id: z6.uuid(),
|
|
2608
2621
|
name: skillNameSchema
|
|
2609
2622
|
});
|
|
2610
2623
|
|
|
2611
2624
|
// ../protocol/src/subscription.ts
|
|
2612
|
-
import { z as
|
|
2625
|
+
import { z as z8 } from "zod";
|
|
2613
2626
|
|
|
2614
2627
|
// ../protocol/src/quota.ts
|
|
2615
|
-
import { z as
|
|
2628
|
+
import { z as z7 } from "zod";
|
|
2616
2629
|
var QUOTA_VENDORS = ["claude_code", "codex", "cursor"];
|
|
2617
|
-
var quotaVendorSchema =
|
|
2630
|
+
var quotaVendorSchema = z7.enum(QUOTA_VENDORS);
|
|
2618
2631
|
var QUOTA_SOURCES = ["local_credentials", "official"];
|
|
2619
|
-
var quotaSourceSchema =
|
|
2632
|
+
var quotaSourceSchema = z7.enum(QUOTA_SOURCES);
|
|
2620
2633
|
var QUOTA_WINDOW_KINDS = [
|
|
2621
2634
|
"five_hour",
|
|
2622
2635
|
"weekly",
|
|
@@ -2625,7 +2638,7 @@ var QUOTA_WINDOW_KINDS = [
|
|
|
2625
2638
|
"hourly",
|
|
2626
2639
|
"other"
|
|
2627
2640
|
];
|
|
2628
|
-
var quotaWindowKindSchema =
|
|
2641
|
+
var quotaWindowKindSchema = z7.enum(QUOTA_WINDOW_KINDS);
|
|
2629
2642
|
var QUOTA_METERS = [
|
|
2630
2643
|
"auto",
|
|
2631
2644
|
"api",
|
|
@@ -2633,142 +2646,142 @@ var QUOTA_METERS = [
|
|
|
2633
2646
|
"team_pool",
|
|
2634
2647
|
"team_on_demand"
|
|
2635
2648
|
];
|
|
2636
|
-
var quotaMeterSchema =
|
|
2637
|
-
var quotaWindowSchema =
|
|
2649
|
+
var quotaMeterSchema = z7.enum(QUOTA_METERS);
|
|
2650
|
+
var quotaWindowSchema = z7.object({
|
|
2638
2651
|
kind: quotaWindowKindSchema,
|
|
2639
2652
|
/** 0..1 share of the window already used. */
|
|
2640
|
-
used:
|
|
2641
|
-
resetsAt:
|
|
2653
|
+
used: z7.number().min(0).max(1),
|
|
2654
|
+
resetsAt: z7.string().nullable(),
|
|
2642
2655
|
/** Model display name for a per-model window, e.g. "Opus". */
|
|
2643
|
-
model:
|
|
2656
|
+
model: z7.string().min(1).max(40).optional(),
|
|
2644
2657
|
meter: quotaMeterSchema.optional()
|
|
2645
2658
|
});
|
|
2646
|
-
var quotaSnapshotSchema =
|
|
2659
|
+
var quotaSnapshotSchema = z7.object({
|
|
2647
2660
|
vendor: quotaVendorSchema,
|
|
2648
2661
|
source: quotaSourceSchema,
|
|
2649
|
-
status:
|
|
2650
|
-
plan:
|
|
2651
|
-
windows:
|
|
2662
|
+
status: z7.enum(["ok", "unknown"]),
|
|
2663
|
+
plan: z7.string().max(40).nullable(),
|
|
2664
|
+
windows: z7.array(quotaWindowSchema).max(12),
|
|
2652
2665
|
/** When this vendor was last read (ISO-8601). */
|
|
2653
|
-
observedAt:
|
|
2666
|
+
observedAt: z7.string()
|
|
2654
2667
|
});
|
|
2655
|
-
var quotaSnapshotReportSchema =
|
|
2668
|
+
var quotaSnapshotReportSchema = z7.object({
|
|
2656
2669
|
/** When the whole read finished. Null before the first read. */
|
|
2657
|
-
observedAt:
|
|
2658
|
-
quotas:
|
|
2670
|
+
observedAt: z7.string().nullable(),
|
|
2671
|
+
quotas: z7.array(quotaSnapshotSchema).max(6)
|
|
2659
2672
|
});
|
|
2660
2673
|
|
|
2661
2674
|
// ../protocol/src/subscription.ts
|
|
2662
|
-
var id2 =
|
|
2663
|
-
var subscriptionRouteSchema =
|
|
2675
|
+
var id2 = z8.string().min(1).max(128);
|
|
2676
|
+
var subscriptionRouteSchema = z8.enum([
|
|
2664
2677
|
"codex_cli",
|
|
2665
2678
|
"claude_code_cli",
|
|
2666
2679
|
"codex_cpa",
|
|
2667
2680
|
"claude_cpa",
|
|
2668
2681
|
"openai_siwc"
|
|
2669
2682
|
]);
|
|
2670
|
-
var subscriptionConnectionSchema =
|
|
2683
|
+
var subscriptionConnectionSchema = z8.object({
|
|
2671
2684
|
id: id2,
|
|
2672
2685
|
ownerId: id2,
|
|
2673
2686
|
workspaceId: id2,
|
|
2674
|
-
provider:
|
|
2675
|
-
state:
|
|
2687
|
+
provider: z8.enum(["openai", "anthropic"]),
|
|
2688
|
+
state: z8.enum([
|
|
2676
2689
|
"pending",
|
|
2677
2690
|
"connected",
|
|
2678
2691
|
"reconnect_required",
|
|
2679
2692
|
"disconnected"
|
|
2680
2693
|
]),
|
|
2681
2694
|
// Increment on reconnect/disconnect. Old bindings cannot become valid again.
|
|
2682
|
-
revision:
|
|
2695
|
+
revision: z8.number().int().positive(),
|
|
2683
2696
|
quota: quotaSnapshotSchema
|
|
2684
2697
|
}).strict();
|
|
2685
|
-
var subscriptionBindingSchema =
|
|
2698
|
+
var subscriptionBindingSchema = z8.object({
|
|
2686
2699
|
id: id2,
|
|
2687
2700
|
ownerId: id2,
|
|
2688
2701
|
workspaceId: id2,
|
|
2689
2702
|
// An agent or assistant session selected explicitly by the owner.
|
|
2690
2703
|
consumerId: id2,
|
|
2691
2704
|
connectionId: id2,
|
|
2692
|
-
connectionRevision:
|
|
2705
|
+
connectionRevision: z8.number().int().positive(),
|
|
2693
2706
|
route: subscriptionRouteSchema
|
|
2694
2707
|
}).strict();
|
|
2695
|
-
var nativeBrokerContextSchema =
|
|
2696
|
-
route:
|
|
2697
|
-
modelId:
|
|
2698
|
-
revision:
|
|
2699
|
-
accountId:
|
|
2700
|
-
plan:
|
|
2701
|
-
expiresAt:
|
|
2708
|
+
var nativeBrokerContextSchema = z8.object({
|
|
2709
|
+
route: z8.enum(["codex_cli", "claude_code_cli"]),
|
|
2710
|
+
modelId: z8.string().min(1).max(128),
|
|
2711
|
+
revision: z8.number().int().positive(),
|
|
2712
|
+
accountId: z8.string().min(1).max(512),
|
|
2713
|
+
plan: z8.string().max(40).optional(),
|
|
2714
|
+
expiresAt: z8.iso.datetime()
|
|
2702
2715
|
}).strict();
|
|
2703
2716
|
var nativeLeaseSchema = nativeBrokerContextSchema.extend({
|
|
2704
|
-
accessToken:
|
|
2717
|
+
accessToken: z8.string().min(1).max(32768).regex(/^[^\r\n\0]+$/)
|
|
2705
2718
|
}).strict();
|
|
2706
2719
|
|
|
2707
2720
|
// ../protocol/src/computer.ts
|
|
2708
|
-
import { z as
|
|
2709
|
-
var machineStateSchema =
|
|
2710
|
-
var controlStateSchema =
|
|
2711
|
-
var computerToolSchema =
|
|
2712
|
-
var screenRectSchema =
|
|
2713
|
-
var computerActionSchema =
|
|
2714
|
-
var lastActionSchema = computerActionSchema.omit({ text: true }).extend({ at:
|
|
2715
|
-
var approvalViewSchema =
|
|
2716
|
-
id:
|
|
2717
|
-
digest:
|
|
2718
|
-
runId:
|
|
2719
|
-
botId:
|
|
2721
|
+
import { z as z9 } from "zod";
|
|
2722
|
+
var machineStateSchema = z9.enum(["sleeping", "waking", "running", "error"]);
|
|
2723
|
+
var controlStateSchema = z9.enum(["agent", "user", "idle"]);
|
|
2724
|
+
var computerToolSchema = z9.enum(["click", "type", "key", "scroll", "screenshot"]);
|
|
2725
|
+
var screenRectSchema = z9.object({ x: z9.number(), y: z9.number(), w: z9.number().nonnegative(), h: z9.number().nonnegative() });
|
|
2726
|
+
var computerActionSchema = z9.object({ tool: computerToolSchema, x: z9.number().optional(), y: z9.number().optional(), text: z9.string().optional(), rect: screenRectSchema.optional() });
|
|
2727
|
+
var lastActionSchema = computerActionSchema.omit({ text: true }).extend({ at: z9.iso.datetime() });
|
|
2728
|
+
var approvalViewSchema = z9.object({
|
|
2729
|
+
id: z9.string(),
|
|
2730
|
+
digest: z9.string(),
|
|
2731
|
+
runId: z9.string(),
|
|
2732
|
+
botId: z9.string(),
|
|
2720
2733
|
action: computerActionSchema,
|
|
2721
|
-
summary:
|
|
2722
|
-
expiresAt:
|
|
2734
|
+
summary: z9.string(),
|
|
2735
|
+
expiresAt: z9.iso.datetime()
|
|
2723
2736
|
});
|
|
2724
|
-
var computerStateSchema =
|
|
2737
|
+
var computerStateSchema = z9.object({
|
|
2725
2738
|
machine: machineStateSchema,
|
|
2726
2739
|
control: controlStateSchema,
|
|
2727
|
-
controlledBy:
|
|
2740
|
+
controlledBy: z9.object({ userId: z9.string() }).optional(),
|
|
2728
2741
|
lastAction: lastActionSchema.optional(),
|
|
2729
2742
|
pendingApproval: approvalViewSchema.optional()
|
|
2730
2743
|
});
|
|
2731
|
-
var viewerModeSchema =
|
|
2732
|
-
var viewerRequestSchema =
|
|
2733
|
-
var viewerGrantSchema =
|
|
2734
|
-
var createBotSchema =
|
|
2735
|
-
var botViewSchema =
|
|
2736
|
-
var approvalDecisionSchema =
|
|
2737
|
-
var computerTaskStateSchema =
|
|
2738
|
-
var computerTaskSchema =
|
|
2739
|
-
var computerEventSchema =
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
+
var viewerModeSchema = z9.enum(["view", "control"]);
|
|
2745
|
+
var viewerRequestSchema = z9.object({ mode: viewerModeSchema }).strict();
|
|
2746
|
+
var viewerGrantSchema = z9.object({ url: z9.url({ protocol: /^wss$/ }), expiresAt: z9.iso.datetime() });
|
|
2747
|
+
var createBotSchema = z9.object({ name: z9.string().trim().min(1).max(120) }).strict();
|
|
2748
|
+
var botViewSchema = z9.object({ id: z9.uuid(), name: z9.string().min(1).max(120) });
|
|
2749
|
+
var approvalDecisionSchema = z9.object({ digest: z9.string(), decision: z9.enum(["approve", "deny"]), scope: z9.enum(["once", "run"]) }).strict();
|
|
2750
|
+
var computerTaskStateSchema = z9.enum(["working", "approval", "done", "failed"]);
|
|
2751
|
+
var computerTaskSchema = z9.object({ botId: z9.string(), runId: z9.string(), task: z9.string(), state: computerTaskStateSchema, approvalId: z9.string().optional() });
|
|
2752
|
+
var computerEventSchema = z9.discriminatedUnion("type", [
|
|
2753
|
+
z9.object({ type: z9.literal("computer.machine"), state: machineStateSchema }),
|
|
2754
|
+
z9.object({ type: z9.literal("computer.control"), botId: z9.string(), control: controlStateSchema, controlledBy: z9.object({ userId: z9.string() }).optional() }),
|
|
2755
|
+
z9.object({ type: z9.literal("computer.action"), botId: z9.string(), lastAction: lastActionSchema }),
|
|
2756
|
+
z9.object({ type: z9.literal("computer.approval"), botId: z9.string(), approval: approvalViewSchema.nullable() })
|
|
2744
2757
|
]);
|
|
2745
|
-
var reviewDigestSchema =
|
|
2746
|
-
var localComputerCall =
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
key:
|
|
2752
|
-
modifiers:
|
|
2758
|
+
var reviewDigestSchema = z9.string().regex(/^[a-f0-9]{64}$/);
|
|
2759
|
+
var localComputerCall = z9.discriminatedUnion("name", [
|
|
2760
|
+
z9.object({ name: z9.literal("get_desktop_state"), arguments: z9.object({}).strict() }).strict(),
|
|
2761
|
+
z9.object({ name: z9.literal("click"), arguments: z9.object({ x: z9.number().int().min(0).max(1e5), y: z9.number().int().min(0).max(1e5) }).strict() }).strict(),
|
|
2762
|
+
z9.object({ name: z9.literal("type_text"), arguments: z9.object({ text: z9.string().min(1).max(8e3) }).strict() }).strict(),
|
|
2763
|
+
z9.object({ name: z9.literal("press_key"), arguments: z9.object({
|
|
2764
|
+
key: z9.string().regex(/^(?:[\x20-\x7e]|enter|return|tab|escape|space|backspace|delete|insert|home|end|pageup|pagedown|up|down|left|right|f(?:[1-9]|1[0-2]))$/),
|
|
2765
|
+
modifiers: z9.array(z9.enum(["ctrl", "shift", "alt", "super"])).max(4).refine((items) => new Set(items).size === items.length).optional()
|
|
2753
2766
|
}).strict() }).strict(),
|
|
2754
|
-
|
|
2767
|
+
z9.object({ name: z9.literal("scroll"), arguments: z9.object({ direction: z9.enum(["up", "down", "left", "right"]), amount: z9.number().int().min(1).max(50), x: z9.number().int().min(0).max(1e5), y: z9.number().int().min(0).max(1e5) }).strict() }).strict()
|
|
2755
2768
|
]);
|
|
2756
|
-
var localComputerRequest =
|
|
2757
|
-
id:
|
|
2758
|
-
runId:
|
|
2769
|
+
var localComputerRequest = z9.object({
|
|
2770
|
+
id: z9.uuid(),
|
|
2771
|
+
runId: z9.uuid(),
|
|
2759
2772
|
target: reviewDigestSchema,
|
|
2760
|
-
display:
|
|
2773
|
+
display: z9.string().regex(/^:[1-9][0-9]{0,2}$/).optional(),
|
|
2761
2774
|
call: localComputerCall,
|
|
2762
|
-
expiresAt:
|
|
2775
|
+
expiresAt: z9.number().int().positive(),
|
|
2763
2776
|
digest: reviewDigestSchema
|
|
2764
2777
|
}).strict();
|
|
2765
|
-
var localComputerDecision =
|
|
2766
|
-
var computerSyncBody =
|
|
2767
|
-
var computerSyncResponse =
|
|
2778
|
+
var localComputerDecision = z9.object({ id: z9.uuid(), digest: reviewDigestSchema, approve: z9.boolean() }).strict();
|
|
2779
|
+
var computerSyncBody = z9.object({ requests: z9.array(localComputerRequest).max(20) }).strict();
|
|
2780
|
+
var computerSyncResponse = z9.object({ decisions: z9.array(localComputerDecision).max(20) }).strict();
|
|
2768
2781
|
var computerSyncPath = (deviceId) => `/v1/devices/${encodeURIComponent(deviceId)}/computer`;
|
|
2769
2782
|
|
|
2770
2783
|
// ../protocol/src/capture.ts
|
|
2771
|
-
import { z as
|
|
2784
|
+
import { z as z10 } from "zod";
|
|
2772
2785
|
var CAPTURE_CONTENT_TYPES = [
|
|
2773
2786
|
"image/png",
|
|
2774
2787
|
"image/jpeg",
|
|
@@ -2784,47 +2797,47 @@ var CAPTURE_MAX_BYTES = {
|
|
|
2784
2797
|
};
|
|
2785
2798
|
var RECORDING_MAX_SECONDS = 300;
|
|
2786
2799
|
var CAPTURE_TITLE_MAX = 200;
|
|
2787
|
-
var sha256 =
|
|
2788
|
-
var title =
|
|
2789
|
-
var captureUploadRequest =
|
|
2800
|
+
var sha256 = z10.string().regex(/^[a-f0-9]{64}$/);
|
|
2801
|
+
var title = z10.string().trim().min(1).max(CAPTURE_TITLE_MAX);
|
|
2802
|
+
var captureUploadRequest = z10.object({
|
|
2790
2803
|
/** Stable client id, persisted before the first network attempt. */
|
|
2791
|
-
captureId:
|
|
2804
|
+
captureId: z10.uuid().optional(),
|
|
2792
2805
|
title,
|
|
2793
|
-
contentType:
|
|
2794
|
-
size:
|
|
2806
|
+
contentType: z10.enum(CAPTURE_CONTENT_TYPES),
|
|
2807
|
+
size: z10.number().int().min(1).max(CAPTURE_MAX_BYTES.video),
|
|
2795
2808
|
sha256
|
|
2796
2809
|
}).strict();
|
|
2797
|
-
var captureUploadTarget =
|
|
2798
|
-
|
|
2799
|
-
|
|
2810
|
+
var captureUploadTarget = z10.discriminatedUnion("target", [
|
|
2811
|
+
z10.object({ target: z10.literal("storage"), url: z10.url({ protocol: /^https$/ }), headers: z10.record(z10.string(), z10.string()) }),
|
|
2812
|
+
z10.object({ target: z10.literal("server") })
|
|
2800
2813
|
]);
|
|
2801
|
-
var captureUploadResponse =
|
|
2802
|
-
captureId:
|
|
2814
|
+
var captureUploadResponse = z10.object({
|
|
2815
|
+
captureId: z10.uuid(),
|
|
2803
2816
|
upload: captureUploadTarget
|
|
2804
2817
|
});
|
|
2805
|
-
var captureView =
|
|
2806
|
-
id:
|
|
2807
|
-
kind:
|
|
2808
|
-
contentType:
|
|
2809
|
-
title:
|
|
2810
|
-
size:
|
|
2811
|
-
durationMs:
|
|
2812
|
-
source:
|
|
2813
|
-
createdAt:
|
|
2818
|
+
var captureView = z10.object({
|
|
2819
|
+
id: z10.uuid(),
|
|
2820
|
+
kind: z10.enum(CAPTURE_KINDS),
|
|
2821
|
+
contentType: z10.enum(CAPTURE_CONTENT_TYPES),
|
|
2822
|
+
title: z10.string(),
|
|
2823
|
+
size: z10.number().int().nonnegative(),
|
|
2824
|
+
durationMs: z10.number().int().nonnegative().nullable(),
|
|
2825
|
+
source: z10.enum(CAPTURE_SOURCES),
|
|
2826
|
+
createdAt: z10.iso.datetime()
|
|
2814
2827
|
});
|
|
2815
|
-
var captureCompleteResponse =
|
|
2816
|
-
var screenCaptureRequest =
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2828
|
+
var captureCompleteResponse = z10.object({ capture: captureView });
|
|
2829
|
+
var screenCaptureRequest = z10.discriminatedUnion("action", [
|
|
2830
|
+
z10.object({ action: z10.literal("screenshot"), title }).strict(),
|
|
2831
|
+
z10.object({ action: z10.literal("start_recording"), title, maxSeconds: z10.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
|
|
2832
|
+
z10.object({ action: z10.literal("stop_recording") }).strict(),
|
|
2820
2833
|
// A step on the recording's timeline: an action's own description, or a moment the agent marks.
|
|
2821
|
-
|
|
2834
|
+
z10.object({ action: z10.literal("step"), label: title, source: z10.enum(["action", "mark"]) }).strict()
|
|
2822
2835
|
]);
|
|
2823
|
-
var screenCaptureResponse =
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2836
|
+
var screenCaptureResponse = z10.discriminatedUnion("action", [
|
|
2837
|
+
z10.object({ action: z10.literal("screenshot"), capture: captureView }),
|
|
2838
|
+
z10.object({ action: z10.literal("start_recording"), recordingId: z10.uuid(), stopsAt: z10.iso.datetime() }),
|
|
2839
|
+
z10.object({ action: z10.literal("stop_recording"), capture: captureView }),
|
|
2840
|
+
z10.object({ action: z10.literal("step"), recorded: z10.boolean() })
|
|
2828
2841
|
]);
|
|
2829
2842
|
var capturePaths = {
|
|
2830
2843
|
begin: (runId) => `/v1/runs/${encodeURIComponent(runId)}/captures`,
|
|
@@ -2834,31 +2847,31 @@ var capturePaths = {
|
|
|
2834
2847
|
};
|
|
2835
2848
|
|
|
2836
2849
|
// ../protocol/src/accounts.ts
|
|
2837
|
-
import { z as
|
|
2838
|
-
var connectedAccount =
|
|
2850
|
+
import { z as z11 } from "zod";
|
|
2851
|
+
var connectedAccount = z11.object({
|
|
2839
2852
|
/** The provider, e.g. "github". Unique per person, so it names the row. */
|
|
2840
|
-
providerId:
|
|
2853
|
+
providerId: z11.string(),
|
|
2841
2854
|
/**
|
|
2842
2855
|
* The account's id at the provider. Better Auth stores the provider's own
|
|
2843
2856
|
* user id here, which for GitHub is a number — the closest thing to a
|
|
2844
2857
|
* display name the table holds.
|
|
2845
2858
|
*/
|
|
2846
|
-
accountId:
|
|
2859
|
+
accountId: z11.string(),
|
|
2847
2860
|
/** OAuth scopes granted, space separated. Null when the provider sent none. */
|
|
2848
|
-
scope:
|
|
2861
|
+
scope: z11.string().nullable(),
|
|
2849
2862
|
/** When the account was linked, ISO 8601. */
|
|
2850
|
-
createdAt:
|
|
2863
|
+
createdAt: z11.string()
|
|
2851
2864
|
});
|
|
2852
|
-
var connectedAccountsResponse =
|
|
2853
|
-
accounts:
|
|
2865
|
+
var connectedAccountsResponse = z11.object({
|
|
2866
|
+
accounts: z11.array(connectedAccount)
|
|
2854
2867
|
});
|
|
2855
2868
|
|
|
2856
2869
|
// ../protocol/src/auth.ts
|
|
2857
|
-
import { z as
|
|
2870
|
+
import { z as z12 } from "zod";
|
|
2858
2871
|
var AUTH_PROVIDERS = ["github", "google"];
|
|
2859
|
-
var authProvider =
|
|
2872
|
+
var authProvider = z12.enum(AUTH_PROVIDERS);
|
|
2860
2873
|
var DESKTOP_SCHEMES = ["mikka", "mikka-dev"];
|
|
2861
|
-
var desktopScheme =
|
|
2874
|
+
var desktopScheme = z12.enum(DESKTOP_SCHEMES);
|
|
2862
2875
|
var AUTH_BASE_PATH = "/api/auth";
|
|
2863
2876
|
var AUTH_ROUTES = {
|
|
2864
2877
|
/** Better Auth jwt plugin: short-lived JWT for zero-cache and the relay. */
|
|
@@ -2867,98 +2880,98 @@ var AUTH_ROUTES = {
|
|
|
2867
2880
|
devLogin: `${AUTH_BASE_PATH}/dev/login`,
|
|
2868
2881
|
me: "/v1/me"
|
|
2869
2882
|
};
|
|
2870
|
-
var activeSession =
|
|
2871
|
-
id:
|
|
2883
|
+
var activeSession = z12.object({
|
|
2884
|
+
id: z12.string(),
|
|
2872
2885
|
/** ISO timestamps. */
|
|
2873
|
-
createdAt:
|
|
2874
|
-
expiresAt:
|
|
2875
|
-
ipAddress:
|
|
2876
|
-
userAgent:
|
|
2886
|
+
createdAt: z12.string(),
|
|
2887
|
+
expiresAt: z12.string(),
|
|
2888
|
+
ipAddress: z12.string().nullable(),
|
|
2889
|
+
userAgent: z12.string().nullable(),
|
|
2877
2890
|
/** Derived from the caller's JWT (`sid`), not from the request's cookies. */
|
|
2878
|
-
current:
|
|
2891
|
+
current: z12.boolean()
|
|
2879
2892
|
});
|
|
2880
|
-
var activeSessions =
|
|
2881
|
-
var authorizedDevice =
|
|
2882
|
-
id:
|
|
2883
|
-
name:
|
|
2884
|
-
hostname:
|
|
2885
|
-
platform:
|
|
2886
|
-
daemonVersion:
|
|
2887
|
-
lastSeenAt:
|
|
2893
|
+
var activeSessions = z12.object({ sessions: z12.array(activeSession) });
|
|
2894
|
+
var authorizedDevice = z12.object({
|
|
2895
|
+
id: z12.uuid(),
|
|
2896
|
+
name: z12.string(),
|
|
2897
|
+
hostname: z12.string().nullable(),
|
|
2898
|
+
platform: z12.string().nullable(),
|
|
2899
|
+
daemonVersion: z12.string().nullable(),
|
|
2900
|
+
lastSeenAt: z12.string().nullable(),
|
|
2888
2901
|
/** The daemon session; null once the authorization is revoked. */
|
|
2889
|
-
sessionId:
|
|
2902
|
+
sessionId: z12.string().nullable(),
|
|
2890
2903
|
/** When the daemon signed in, and when that session expires. */
|
|
2891
|
-
authorizedAt:
|
|
2892
|
-
expiresAt:
|
|
2904
|
+
authorizedAt: z12.string().nullable(),
|
|
2905
|
+
expiresAt: z12.string().nullable()
|
|
2893
2906
|
});
|
|
2894
|
-
var authorizedDevices =
|
|
2895
|
-
devices:
|
|
2907
|
+
var authorizedDevices = z12.object({
|
|
2908
|
+
devices: z12.array(authorizedDevice)
|
|
2896
2909
|
});
|
|
2897
|
-
var authorizedApplication =
|
|
2898
|
-
id:
|
|
2899
|
-
name:
|
|
2900
|
-
uri:
|
|
2901
|
-
scopes:
|
|
2902
|
-
createdAt:
|
|
2903
|
-
updatedAt:
|
|
2910
|
+
var authorizedApplication = z12.object({
|
|
2911
|
+
id: z12.string(),
|
|
2912
|
+
name: z12.string(),
|
|
2913
|
+
uri: z12.string().nullable(),
|
|
2914
|
+
scopes: z12.array(z12.string()),
|
|
2915
|
+
createdAt: z12.string(),
|
|
2916
|
+
updatedAt: z12.string()
|
|
2904
2917
|
});
|
|
2905
|
-
var authorizedApplications =
|
|
2906
|
-
applications:
|
|
2918
|
+
var authorizedApplications = z12.object({
|
|
2919
|
+
applications: z12.array(authorizedApplication)
|
|
2907
2920
|
});
|
|
2908
|
-
var sessionUser =
|
|
2909
|
-
id:
|
|
2910
|
-
email:
|
|
2911
|
-
name:
|
|
2912
|
-
image:
|
|
2921
|
+
var sessionUser = z12.object({
|
|
2922
|
+
id: z12.uuid(),
|
|
2923
|
+
email: z12.string(),
|
|
2924
|
+
name: z12.string(),
|
|
2925
|
+
image: z12.string().nullable()
|
|
2913
2926
|
});
|
|
2914
|
-
var accessToken =
|
|
2915
|
-
token:
|
|
2927
|
+
var accessToken = z12.object({
|
|
2928
|
+
token: z12.string().min(1),
|
|
2916
2929
|
/** Expiry, ms since epoch (from the JWT's `exp`). */
|
|
2917
|
-
expiresAt:
|
|
2930
|
+
expiresAt: z12.number().int()
|
|
2918
2931
|
});
|
|
2919
2932
|
|
|
2920
2933
|
// ../protocol/src/bridge.ts
|
|
2921
|
-
import { z as
|
|
2934
|
+
import { z as z13 } from "zod";
|
|
2922
2935
|
var LANGUAGES = ["zh-CN", "en"];
|
|
2923
|
-
var languagePreference =
|
|
2924
|
-
var themePreference =
|
|
2925
|
-
var appHref =
|
|
2936
|
+
var languagePreference = z13.enum(["system", ...LANGUAGES]);
|
|
2937
|
+
var themePreference = z13.enum(["system", "light", "dark"]);
|
|
2938
|
+
var appHref = z13.string().max(2048).regex(/^\/(?!\/)/);
|
|
2926
2939
|
var DESKTOP_NOTIFICATION_KINDS = [
|
|
2927
2940
|
"review",
|
|
2928
2941
|
"awaiting",
|
|
2929
2942
|
"failed",
|
|
2930
2943
|
"finished"
|
|
2931
2944
|
];
|
|
2932
|
-
var desktopNotification =
|
|
2945
|
+
var desktopNotification = z13.object({
|
|
2933
2946
|
/** The `notification` row id. */
|
|
2934
|
-
id:
|
|
2935
|
-
kind:
|
|
2947
|
+
id: z13.string().min(1).max(200),
|
|
2948
|
+
kind: z13.enum(DESKTOP_NOTIFICATION_KINDS),
|
|
2936
2949
|
/** `ORV-12 · 等你验收`; the issue number is always in it. */
|
|
2937
|
-
title:
|
|
2950
|
+
title: z13.string().min(1).max(300),
|
|
2938
2951
|
/** The issue title. */
|
|
2939
|
-
body:
|
|
2952
|
+
body: z13.string().max(1e3),
|
|
2940
2953
|
href: appHref
|
|
2941
2954
|
});
|
|
2942
|
-
var desktopBadgeCount =
|
|
2943
|
-
var savedTab =
|
|
2944
|
-
entries:
|
|
2945
|
-
index:
|
|
2955
|
+
var desktopBadgeCount = z13.number().int().min(0).max(9999);
|
|
2956
|
+
var savedTab = z13.object({
|
|
2957
|
+
entries: z13.array(appHref).min(1).max(50),
|
|
2958
|
+
index: z13.number().int().min(0).max(49)
|
|
2946
2959
|
});
|
|
2947
|
-
var savedTabs =
|
|
2948
|
-
items:
|
|
2949
|
-
active:
|
|
2960
|
+
var savedTabs = z13.object({
|
|
2961
|
+
items: z13.array(savedTab).max(50),
|
|
2962
|
+
active: z13.number().int().min(0).max(49)
|
|
2950
2963
|
});
|
|
2951
|
-
var firstDayOfWeekPreference =
|
|
2952
|
-
var commentSubmitKeyPreference =
|
|
2953
|
-
var settingsSchema =
|
|
2964
|
+
var firstDayOfWeekPreference = z13.enum(["monday", "sunday", "saturday"]);
|
|
2965
|
+
var commentSubmitKeyPreference = z13.enum(["mod+enter", "enter"]);
|
|
2966
|
+
var settingsSchema = z13.object({
|
|
2954
2967
|
language: languagePreference,
|
|
2955
2968
|
theme: themePreference,
|
|
2956
2969
|
/** Sidebar expanded (true) or collapsed offcanvas (false); ⌘B and `[`. */
|
|
2957
|
-
sidebarOpen:
|
|
2970
|
+
sidebarOpen: z13.boolean(),
|
|
2958
2971
|
/** Titlebar tabs; empty until the app has saved them once. */
|
|
2959
2972
|
tabs: savedTabs,
|
|
2960
2973
|
/** Send anonymous usage events (ADR 0033); off by choice in Settings. */
|
|
2961
|
-
telemetry:
|
|
2974
|
+
telemetry: z13.boolean(),
|
|
2962
2975
|
/** Which day a week starts on in date pickers. */
|
|
2963
2976
|
firstDayOfWeek: firstDayOfWeekPreference,
|
|
2964
2977
|
/** Which key press sends a comment. */
|
|
@@ -2974,43 +2987,43 @@ var DEFAULT_SETTINGS = {
|
|
|
2974
2987
|
commentSubmitKey: "mod+enter"
|
|
2975
2988
|
};
|
|
2976
2989
|
var SETTINGS_KEYS = Object.keys(DEFAULT_SETTINGS);
|
|
2977
|
-
var authState =
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
status:
|
|
2983
|
-
minVersion:
|
|
2990
|
+
var authState = z13.discriminatedUnion("status", [
|
|
2991
|
+
z13.object({ status: z13.literal("signed_out") }),
|
|
2992
|
+
z13.object({ status: z13.literal("signing_in"), provider: authProvider }),
|
|
2993
|
+
z13.object({ status: z13.literal("signed_in"), user: sessionUser }),
|
|
2994
|
+
z13.object({
|
|
2995
|
+
status: z13.literal("update_required"),
|
|
2996
|
+
minVersion: z13.string()
|
|
2984
2997
|
}),
|
|
2985
|
-
|
|
2998
|
+
z13.object({ status: z13.literal("error"), code: z13.string() })
|
|
2986
2999
|
]);
|
|
2987
|
-
var localDevice =
|
|
3000
|
+
var localDevice = z13.object({
|
|
2988
3001
|
/** Whether the daemon on this computer answers. */
|
|
2989
|
-
status:
|
|
3002
|
+
status: z13.enum(["online", "connecting", "offline"]),
|
|
2990
3003
|
/** The device row this daemon registered, once it has. */
|
|
2991
|
-
deviceId:
|
|
2992
|
-
workspaceId:
|
|
3004
|
+
deviceId: z13.string().nullable(),
|
|
3005
|
+
workspaceId: z13.string().nullable(),
|
|
2993
3006
|
/** The daemon holds a device credential. */
|
|
2994
|
-
signedIn:
|
|
3007
|
+
signedIn: z13.boolean(),
|
|
2995
3008
|
/** The daemon's link to the server; null while the daemon is offline. */
|
|
2996
|
-
server:
|
|
3009
|
+
server: z13.enum(["online", "offline", "unregistered"]).nullable()
|
|
2997
3010
|
});
|
|
2998
|
-
var deviceLinkRequest =
|
|
2999
|
-
var pickedRepo =
|
|
3011
|
+
var deviceLinkRequest = z13.object({ workspaceId: z13.uuid() });
|
|
3012
|
+
var pickedRepo = z13.object({
|
|
3000
3013
|
/** The repo's top level (a subfolder pick resolves to it). */
|
|
3001
|
-
path:
|
|
3002
|
-
name:
|
|
3014
|
+
path: z13.string().min(1).max(4e3),
|
|
3015
|
+
name: z13.string().max(500),
|
|
3003
3016
|
/** `origin` (or the first remote), null when the repo has none. */
|
|
3004
|
-
remoteUrl:
|
|
3017
|
+
remoteUrl: z13.string().max(2e3).nullable()
|
|
3005
3018
|
});
|
|
3006
|
-
var pickRepoResult =
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3019
|
+
var pickRepoResult = z13.discriminatedUnion("status", [
|
|
3020
|
+
z13.object({ status: z13.literal("picked"), repo: pickedRepo }),
|
|
3021
|
+
z13.object({ status: z13.literal("cancelled") }),
|
|
3022
|
+
z13.object({ status: z13.literal("not_a_repo"), path: z13.string() })
|
|
3010
3023
|
]);
|
|
3011
3024
|
|
|
3012
3025
|
// ../protocol/src/cycles.ts
|
|
3013
|
-
import { z as
|
|
3026
|
+
import { z as z14 } from "zod";
|
|
3014
3027
|
var WEEKDAYS = [
|
|
3015
3028
|
"monday",
|
|
3016
3029
|
"tuesday",
|
|
@@ -3023,26 +3036,26 @@ var WEEKDAYS = [
|
|
|
3023
3036
|
var CYCLE_DURATION_MIN_DAYS = 1;
|
|
3024
3037
|
var CYCLE_DURATION_MAX_DAYS = 56;
|
|
3025
3038
|
var CYCLE_UPCOMING_MAX = 8;
|
|
3026
|
-
var teamCycleSettingsSchema =
|
|
3039
|
+
var teamCycleSettingsSchema = z14.object({
|
|
3027
3040
|
/** Off until a person turns it on: nothing is created and nothing rolls. */
|
|
3028
|
-
enabled:
|
|
3041
|
+
enabled: z14.boolean().default(false),
|
|
3029
3042
|
/** Length of a cycle in days; the end date is `start + duration - 1`. */
|
|
3030
|
-
durationDays:
|
|
3043
|
+
durationDays: z14.number().int().min(CYCLE_DURATION_MIN_DAYS).max(CYCLE_DURATION_MAX_DAYS).default(14),
|
|
3031
3044
|
/** The weekday a team's first cycle starts on. */
|
|
3032
|
-
startWeekday:
|
|
3045
|
+
startWeekday: z14.enum(WEEKDAYS).default("monday"),
|
|
3033
3046
|
/** Cycles kept ready ahead of the current one. 0 creates them just in time. */
|
|
3034
|
-
upcomingCount:
|
|
3047
|
+
upcomingCount: z14.number().int().min(0).max(CYCLE_UPCOMING_MAX).default(1),
|
|
3035
3048
|
/**
|
|
3036
3049
|
* When a cycle ends, unfinished issues move to the next one. Off leaves them
|
|
3037
3050
|
* in the finished cycle, which is what `cycle.complete` has always done.
|
|
3038
3051
|
*/
|
|
3039
|
-
autoRollover:
|
|
3052
|
+
autoRollover: z14.boolean().default(true),
|
|
3040
3053
|
/**
|
|
3041
3054
|
* The team's calendar. A cycle ends at the last moment of its end date
|
|
3042
3055
|
* *here*, not in UTC, so a team in Auckland and one in Los Angeles roll over
|
|
3043
3056
|
* at different instants.
|
|
3044
3057
|
*/
|
|
3045
|
-
timezone:
|
|
3058
|
+
timezone: z14.string().max(64).refine(isValidTimeZone, "Unknown timezone.").default("UTC")
|
|
3046
3059
|
});
|
|
3047
3060
|
function isValidTimeZone(value) {
|
|
3048
3061
|
try {
|
|
@@ -3054,36 +3067,36 @@ function isValidTimeZone(value) {
|
|
|
3054
3067
|
}
|
|
3055
3068
|
|
|
3056
3069
|
// ../protocol/src/daemon.ts
|
|
3057
|
-
import { z as
|
|
3070
|
+
import { z as z18 } from "zod";
|
|
3058
3071
|
|
|
3059
3072
|
// ../protocol/src/harness.ts
|
|
3060
|
-
import { z as
|
|
3073
|
+
import { z as z15 } from "zod";
|
|
3061
3074
|
var HARNESSES = ["claude_code", "codex", "cursor", "mock"];
|
|
3062
|
-
var harnessSchema =
|
|
3063
|
-
var harnessInfoSchema =
|
|
3075
|
+
var harnessSchema = z15.enum(HARNESSES);
|
|
3076
|
+
var harnessInfoSchema = z15.object({
|
|
3064
3077
|
harness: harnessSchema,
|
|
3065
|
-
installed:
|
|
3066
|
-
models:
|
|
3067
|
-
modelSlots:
|
|
3068
|
-
|
|
3069
|
-
slot:
|
|
3070
|
-
model:
|
|
3071
|
-
name:
|
|
3078
|
+
installed: z15.boolean(),
|
|
3079
|
+
models: z15.array(z15.string().trim().min(1).max(128)).max(500).optional(),
|
|
3080
|
+
modelSlots: z15.array(
|
|
3081
|
+
z15.object({
|
|
3082
|
+
slot: z15.string().trim().min(1).max(128).refine((v2) => v2 !== "auto"),
|
|
3083
|
+
model: z15.string().trim().min(1).max(128),
|
|
3084
|
+
name: z15.string().trim().min(1).max(200)
|
|
3072
3085
|
})
|
|
3073
3086
|
).max(500).optional(),
|
|
3074
|
-
defaultModelSlot:
|
|
3087
|
+
defaultModelSlot: z15.string().trim().min(1).max(128).optional(),
|
|
3075
3088
|
/** Deprecated (#312, 2026-10-27): could host the native Coordinator. The server keeps that runtime switched off. */
|
|
3076
|
-
coordinator:
|
|
3089
|
+
coordinator: z15.boolean().optional(),
|
|
3077
3090
|
/**
|
|
3078
3091
|
* Set only by a runner that runs subscriptions under owner-bound custody:
|
|
3079
3092
|
* the hosted runner's broker, or a device daemon that takes one run's
|
|
3080
3093
|
* short-lived access lease (never the refresh grant) and wipes it at run end.
|
|
3081
3094
|
*/
|
|
3082
|
-
subscriptionBroker:
|
|
3095
|
+
subscriptionBroker: z15.literal(true).optional(),
|
|
3083
3096
|
/** Set only by an E2B worker with the guarded Bot computer broker. */
|
|
3084
|
-
computerBroker:
|
|
3097
|
+
computerBroker: z15.literal(true).optional(),
|
|
3085
3098
|
/** Run-scoped CLI approvals and policy-version checks are supported. */
|
|
3086
|
-
toolApproval:
|
|
3099
|
+
toolApproval: z15.literal(true).optional(),
|
|
3087
3100
|
/**
|
|
3088
3101
|
* The CLI exists but `installed` stays false because the daemon cannot run it
|
|
3089
3102
|
* in a sandbox. `missing` names the absent packages; empty means the machine
|
|
@@ -3091,35 +3104,35 @@ var harnessInfoSchema = z14.object({
|
|
|
3091
3104
|
* (`userns_restricted`: Ubuntu's AppArmor user namespace restriction), and
|
|
3092
3105
|
* `detail` is the probe's own error, already sanitized by the daemon.
|
|
3093
3106
|
*/
|
|
3094
|
-
sandboxBlocked:
|
|
3095
|
-
missing:
|
|
3096
|
-
reason:
|
|
3097
|
-
detail:
|
|
3107
|
+
sandboxBlocked: z15.object({
|
|
3108
|
+
missing: z15.array(z15.string().trim().min(1).max(64)).max(8),
|
|
3109
|
+
reason: z15.enum(["userns_restricted"]).optional(),
|
|
3110
|
+
detail: z15.string().max(300).optional()
|
|
3098
3111
|
}).optional(),
|
|
3099
3112
|
/** Version string reported by the CLI, null when not installed. */
|
|
3100
|
-
version:
|
|
3113
|
+
version: z15.string().nullable()
|
|
3101
3114
|
});
|
|
3102
3115
|
|
|
3103
3116
|
// ../protocol/src/run.ts
|
|
3104
|
-
import { z as
|
|
3117
|
+
import { z as z17 } from "zod";
|
|
3105
3118
|
|
|
3106
3119
|
// ../protocol/src/plan.ts
|
|
3107
|
-
import { z as
|
|
3108
|
-
var text = (max) =>
|
|
3109
|
-
var key =
|
|
3110
|
-
var planSection =
|
|
3120
|
+
import { z as z16 } from "zod";
|
|
3121
|
+
var text = (max) => z16.string().trim().min(1).max(max);
|
|
3122
|
+
var key = z16.string().trim().min(1).max(64);
|
|
3123
|
+
var planSection = z16.object({
|
|
3111
3124
|
heading: text(200),
|
|
3112
|
-
items:
|
|
3125
|
+
items: z16.array(text(2e3)).min(1).max(50)
|
|
3113
3126
|
});
|
|
3114
|
-
var planSpec =
|
|
3127
|
+
var planSpec = z16.object({
|
|
3115
3128
|
title: text(500),
|
|
3116
|
-
summary:
|
|
3117
|
-
sections:
|
|
3129
|
+
summary: z16.string().trim().max(4e3).default(""),
|
|
3130
|
+
sections: z16.array(planSection).min(1).max(30)
|
|
3118
3131
|
});
|
|
3119
|
-
var planCriterion =
|
|
3132
|
+
var planCriterion = z16.object({
|
|
3120
3133
|
body: text(2e3),
|
|
3121
3134
|
/** The command that checks it; absent means a person checks it. */
|
|
3122
|
-
checkCommand:
|
|
3135
|
+
checkCommand: z16.string().trim().max(2e3).optional()
|
|
3123
3136
|
});
|
|
3124
3137
|
var PLAN_PRIORITIES = [
|
|
3125
3138
|
"none",
|
|
@@ -3128,25 +3141,25 @@ var PLAN_PRIORITIES = [
|
|
|
3128
3141
|
"medium",
|
|
3129
3142
|
"low"
|
|
3130
3143
|
];
|
|
3131
|
-
var planIssue =
|
|
3144
|
+
var planIssue = z16.object({
|
|
3132
3145
|
key,
|
|
3133
3146
|
title: text(500),
|
|
3134
|
-
goal:
|
|
3147
|
+
goal: z16.string().trim().max(4e3).optional(),
|
|
3135
3148
|
/** Grouping only; order lives in `blockedBy` (`issue.parent_id`). */
|
|
3136
3149
|
parentKey: key.optional(),
|
|
3137
|
-
blockedBy:
|
|
3138
|
-
criteria:
|
|
3139
|
-
verifyCommand:
|
|
3140
|
-
predictedFiles:
|
|
3141
|
-
sizeEstimate:
|
|
3142
|
-
priority:
|
|
3150
|
+
blockedBy: z16.array(key).max(50).default([]),
|
|
3151
|
+
criteria: z16.array(planCriterion).min(1).max(50),
|
|
3152
|
+
verifyCommand: z16.string().trim().max(2e3).optional(),
|
|
3153
|
+
predictedFiles: z16.array(z16.string().trim().max(1e3)).max(200).default([]),
|
|
3154
|
+
sizeEstimate: z16.object({ files: z16.number().int().min(0), lines: z16.number().int().min(0) }).optional(),
|
|
3155
|
+
priority: z16.enum(PLAN_PRIORITIES).default("none")
|
|
3143
3156
|
});
|
|
3144
|
-
var planSplit =
|
|
3145
|
-
summary:
|
|
3146
|
-
issues:
|
|
3157
|
+
var planSplit = z16.object({
|
|
3158
|
+
summary: z16.string().trim().max(4e3).default(""),
|
|
3159
|
+
issues: z16.array(planIssue).min(1).max(100)
|
|
3147
3160
|
});
|
|
3148
|
-
var planHandoff =
|
|
3149
|
-
specId:
|
|
3161
|
+
var planHandoff = z16.object({
|
|
3162
|
+
specId: z16.uuid(),
|
|
3150
3163
|
spec: planSpec,
|
|
3151
3164
|
split: planSplit
|
|
3152
3165
|
});
|
|
@@ -3158,12 +3171,12 @@ var RUN_QUESTION_KINDS = [
|
|
|
3158
3171
|
"permission",
|
|
3159
3172
|
"external"
|
|
3160
3173
|
];
|
|
3161
|
-
var runQuestion =
|
|
3162
|
-
questionId:
|
|
3163
|
-
kind:
|
|
3164
|
-
question:
|
|
3165
|
-
context:
|
|
3166
|
-
options:
|
|
3174
|
+
var runQuestion = z17.object({
|
|
3175
|
+
questionId: z17.uuid(),
|
|
3176
|
+
kind: z17.enum(RUN_QUESTION_KINDS).default("decision"),
|
|
3177
|
+
question: z17.string().trim().min(1).max(4e3),
|
|
3178
|
+
context: z17.string().trim().max(4e3).optional(),
|
|
3179
|
+
options: z17.array(z17.string().trim().min(1).max(4e3)).max(20).default([])
|
|
3167
3180
|
}).strict();
|
|
3168
3181
|
var RUN_STOP_REASONS = [
|
|
3169
3182
|
"submitted",
|
|
@@ -3177,37 +3190,37 @@ var RUN_STOP_REASONS = [
|
|
|
3177
3190
|
/** The subscription's quota or rate limit ran out mid-run (see `resetsAt`). */
|
|
3178
3191
|
"quota_exhausted"
|
|
3179
3192
|
];
|
|
3180
|
-
var runStopReason =
|
|
3181
|
-
var shortList =
|
|
3193
|
+
var runStopReason = z17.enum(RUN_STOP_REASONS);
|
|
3194
|
+
var shortList = z17.array(z17.string().max(1e3)).max(5e3);
|
|
3182
3195
|
var VERIFY_STATUSES = ["passed", "failed", "not_run"];
|
|
3183
|
-
var verifyStatus =
|
|
3184
|
-
var runPublish =
|
|
3196
|
+
var verifyStatus = z17.enum(VERIFY_STATUSES);
|
|
3197
|
+
var runPublish = z17.object({
|
|
3185
3198
|
/** Where the commit went: the issue's branch, or the run's own. */
|
|
3186
|
-
branch:
|
|
3199
|
+
branch: z17.string().max(500),
|
|
3187
3200
|
/** Null when nothing was committed (no changes, or the commit failed). */
|
|
3188
|
-
commit:
|
|
3189
|
-
pushed:
|
|
3190
|
-
remote:
|
|
3201
|
+
commit: z17.string().max(100).nullable(),
|
|
3202
|
+
pushed: z17.boolean(),
|
|
3203
|
+
remote: z17.string().max(200).nullable(),
|
|
3191
3204
|
/**
|
|
3192
3205
|
* Why nothing was pushed when that was expected: the agent changed
|
|
3193
3206
|
* nothing, or the repo has not approved pushes. Absent with
|
|
3194
3207
|
* `pushed: false` means the commit or the push failed (see `note`).
|
|
3195
3208
|
*/
|
|
3196
|
-
skipped:
|
|
3197
|
-
note:
|
|
3209
|
+
skipped: z17.enum(["no_changes", "not_approved"]).optional(),
|
|
3210
|
+
note: z17.string().max(2e3).optional()
|
|
3198
3211
|
});
|
|
3199
|
-
var runBenchmarkContext =
|
|
3200
|
-
sourceCommit:
|
|
3201
|
-
benchmarkDigest:
|
|
3202
|
-
caseId:
|
|
3203
|
-
fixtureDigest:
|
|
3204
|
-
policyDigest:
|
|
3212
|
+
var runBenchmarkContext = z17.object({
|
|
3213
|
+
sourceCommit: z17.string().regex(/^[a-f0-9]{40}$/),
|
|
3214
|
+
benchmarkDigest: z17.string().regex(/^[a-f0-9]{64}$/),
|
|
3215
|
+
caseId: z17.string().min(1).max(200),
|
|
3216
|
+
fixtureDigest: z17.string().regex(/^[a-f0-9]{64}$/),
|
|
3217
|
+
policyDigest: z17.string().regex(/^[a-f0-9]{64}$/)
|
|
3205
3218
|
}).strict();
|
|
3206
3219
|
var runExecution = runBenchmarkContext.extend({
|
|
3207
|
-
harness:
|
|
3208
|
-
requestedModel:
|
|
3209
|
-
observedModel:
|
|
3210
|
-
verifyCommand:
|
|
3220
|
+
harness: z17.enum(["codex", "claude_code", "cursor"]),
|
|
3221
|
+
requestedModel: z17.string().min(1).max(500).nullable(),
|
|
3222
|
+
observedModel: z17.string().min(1).max(500).nullable(),
|
|
3223
|
+
verifyCommand: z17.string().min(1).max(2e3)
|
|
3211
3224
|
}).strict();
|
|
3212
3225
|
var runRuntime = runExecution.pick({
|
|
3213
3226
|
harness: true,
|
|
@@ -3216,62 +3229,62 @@ var runRuntime = runExecution.pick({
|
|
|
3216
3229
|
policyDigest: true,
|
|
3217
3230
|
sourceCommit: true
|
|
3218
3231
|
}).strict();
|
|
3219
|
-
var runSkillMount =
|
|
3220
|
-
receiptId:
|
|
3221
|
-
versionId:
|
|
3222
|
-
sha256:
|
|
3223
|
-
sessionId:
|
|
3224
|
-
mountedAt:
|
|
3232
|
+
var runSkillMount = z17.object({
|
|
3233
|
+
receiptId: z17.uuid(),
|
|
3234
|
+
versionId: z17.uuid(),
|
|
3235
|
+
sha256: z17.string().regex(/^[a-f0-9]{64}$/),
|
|
3236
|
+
sessionId: z17.string().min(1).max(500),
|
|
3237
|
+
mountedAt: z17.iso.datetime()
|
|
3225
3238
|
}).strict();
|
|
3226
|
-
var runReport =
|
|
3239
|
+
var runReport = z17.object({
|
|
3227
3240
|
/** Worktree base journaled before the adapter started; never agent-supplied. */
|
|
3228
|
-
sourceCommit:
|
|
3241
|
+
sourceCommit: z17.string().regex(/^[a-f0-9]{40}$/).optional(),
|
|
3229
3242
|
skillMount: runSkillMount.optional(),
|
|
3230
3243
|
execution: runExecution.optional(),
|
|
3231
3244
|
runtime: runRuntime.optional(),
|
|
3232
3245
|
/** What was done, in a few sentences. Empty when the run crashed early. */
|
|
3233
|
-
summary:
|
|
3246
|
+
summary: z17.string().max(1e4),
|
|
3234
3247
|
/** Paths relative to the worktree root (from `git status`). */
|
|
3235
3248
|
filesChanged: shortList,
|
|
3236
3249
|
/** The daemon's run of the issue's verify command after a submit. */
|
|
3237
|
-
verify:
|
|
3250
|
+
verify: z17.object({
|
|
3238
3251
|
status: verifyStatus,
|
|
3239
|
-
command:
|
|
3252
|
+
command: z17.string().max(2e3).optional(),
|
|
3240
3253
|
/** Actual process outcome from the daemon, never the agent. */
|
|
3241
|
-
exitCode:
|
|
3242
|
-
signal:
|
|
3243
|
-
timedOut:
|
|
3254
|
+
exitCode: z17.number().int().nullable().optional(),
|
|
3255
|
+
signal: z17.string().max(100).nullable().optional(),
|
|
3256
|
+
timedOut: z17.boolean().optional(),
|
|
3244
3257
|
/** Tail of the command output. */
|
|
3245
|
-
output:
|
|
3258
|
+
output: z17.string().max(1e4).optional()
|
|
3246
3259
|
}),
|
|
3247
|
-
openQuestions:
|
|
3260
|
+
openQuestions: z17.array(z17.string().max(2e3)).max(50),
|
|
3248
3261
|
/** What should happen next, from the agent's point of view. */
|
|
3249
3262
|
question: runQuestion.optional(),
|
|
3250
|
-
nextStep:
|
|
3263
|
+
nextStep: z17.string().max(2e3).nullable(),
|
|
3251
3264
|
/** For `blocked`: the external condition, e.g. `quota_exhausted`. */
|
|
3252
|
-
blockedOn:
|
|
3265
|
+
blockedOn: z17.string().max(500).optional(),
|
|
3253
3266
|
/**
|
|
3254
3267
|
* For `quota_exhausted`: when the subscription's quota resets, as the CLI
|
|
3255
3268
|
* reported it; null when it gave no time. Set by the daemon only.
|
|
3256
3269
|
*/
|
|
3257
|
-
resetsAt:
|
|
3270
|
+
resetsAt: z17.iso.datetime({ offset: true }).nullable().optional(),
|
|
3258
3271
|
/** Daemon-owned receipt for an exact, unchanged read-only candidate. */
|
|
3259
|
-
check:
|
|
3260
|
-
sha:
|
|
3261
|
-
readOnly:
|
|
3272
|
+
check: z17.object({
|
|
3273
|
+
sha: z17.string().regex(/^[a-f0-9]{40}$/),
|
|
3274
|
+
readOnly: z17.literal(true)
|
|
3262
3275
|
}).optional(),
|
|
3263
3276
|
/** Preview branch created or used by the producing run; descriptive metadata only. */
|
|
3264
|
-
previewDatabaseBranch:
|
|
3277
|
+
previewDatabaseBranch: z17.string().trim().min(1).max(500).optional(),
|
|
3265
3278
|
/** Acceptance criteria the agent checked, with evidence. */
|
|
3266
|
-
criteria:
|
|
3267
|
-
|
|
3268
|
-
criterionId:
|
|
3269
|
-
text:
|
|
3270
|
-
passed:
|
|
3271
|
-
evidence:
|
|
3279
|
+
criteria: z17.array(
|
|
3280
|
+
z17.object({
|
|
3281
|
+
criterionId: z17.uuid().optional(),
|
|
3282
|
+
text: z17.string().max(2e3).optional(),
|
|
3283
|
+
passed: z17.boolean(),
|
|
3284
|
+
evidence: z17.string().max(1e4).optional(),
|
|
3272
3285
|
/** Agent-reported criterion check; the daemon-owned verify remains authoritative. */
|
|
3273
|
-
command:
|
|
3274
|
-
exitCode:
|
|
3286
|
+
command: z17.string().trim().min(1).max(2e3).optional(),
|
|
3287
|
+
exitCode: z17.number().int().nullable().optional()
|
|
3275
3288
|
})
|
|
3276
3289
|
).max(200).optional(),
|
|
3277
3290
|
/**
|
|
@@ -3281,23 +3294,23 @@ var runReport = z16.object({
|
|
|
3281
3294
|
plan: planHandoff.optional(),
|
|
3282
3295
|
interfacesProduced: shortList.optional(),
|
|
3283
3296
|
knownIssues: shortList.optional(),
|
|
3284
|
-
notesForNext:
|
|
3297
|
+
notesForNext: z17.string().max(1e4).optional(),
|
|
3285
3298
|
/** Set by the daemon after a verified submit; never by the agent. */
|
|
3286
3299
|
publish: runPublish.optional(),
|
|
3287
|
-
followUps:
|
|
3288
|
-
|
|
3289
|
-
title:
|
|
3290
|
-
goal:
|
|
3291
|
-
reason:
|
|
3300
|
+
followUps: z17.array(
|
|
3301
|
+
z17.object({
|
|
3302
|
+
title: z17.string().trim().min(1).max(500),
|
|
3303
|
+
goal: z17.string().max(2e3).optional(),
|
|
3304
|
+
reason: z17.string().max(2e3).optional()
|
|
3292
3305
|
})
|
|
3293
3306
|
).max(50).optional()
|
|
3294
3307
|
});
|
|
3295
3308
|
var runCompletePath = (runId) => `/v1/runs/${encodeURIComponent(runId)}/complete`;
|
|
3296
|
-
var runCompletion =
|
|
3309
|
+
var runCompletion = z17.object({
|
|
3297
3310
|
stopReason: runStopReason,
|
|
3298
3311
|
report: runReport
|
|
3299
3312
|
});
|
|
3300
|
-
var runCompleteRequest =
|
|
3313
|
+
var runCompleteRequest = z17.object({ stopReason: runStopReason, report: runReport.optional() }).refine((body) => body.stopReason !== "submitted" || body.report, {
|
|
3301
3314
|
message: "A submitted run needs a report.",
|
|
3302
3315
|
path: ["report"]
|
|
3303
3316
|
});
|
|
@@ -3315,7 +3328,7 @@ var RUN_STATES = [
|
|
|
3315
3328
|
"failed",
|
|
3316
3329
|
"cancelled"
|
|
3317
3330
|
];
|
|
3318
|
-
var runStateSchema =
|
|
3331
|
+
var runStateSchema = z18.enum(RUN_STATES);
|
|
3319
3332
|
var stopReasonSchema = runStopReason;
|
|
3320
3333
|
var DAEMON_RPC_ERRORS = {
|
|
3321
3334
|
handshakeRequired: 4001,
|
|
@@ -3329,58 +3342,58 @@ var DAEMON_RPC_ERRORS = {
|
|
|
3329
3342
|
serverUnreachable: 4020,
|
|
3330
3343
|
draining: 4030
|
|
3331
3344
|
};
|
|
3332
|
-
var helloParams =
|
|
3333
|
-
protocolVersion:
|
|
3345
|
+
var helloParams = z18.object({
|
|
3346
|
+
protocolVersion: z18.number().int(),
|
|
3334
3347
|
/** Contents of the daemon's `daemon.secret` file in the flavor data dir. */
|
|
3335
|
-
secret:
|
|
3336
|
-
client:
|
|
3348
|
+
secret: z18.string(),
|
|
3349
|
+
client: z18.object({ name: z18.string(), version: z18.string() })
|
|
3337
3350
|
});
|
|
3338
|
-
var helloResult =
|
|
3339
|
-
protocolVersion:
|
|
3340
|
-
daemonVersion:
|
|
3341
|
-
pid:
|
|
3351
|
+
var helloResult = z18.object({
|
|
3352
|
+
protocolVersion: z18.number().int(),
|
|
3353
|
+
daemonVersion: z18.string(),
|
|
3354
|
+
pid: z18.number().int()
|
|
3342
3355
|
});
|
|
3343
|
-
var runSummarySchema =
|
|
3344
|
-
runId:
|
|
3345
|
-
issueId:
|
|
3356
|
+
var runSummarySchema = z18.object({
|
|
3357
|
+
runId: z18.string(),
|
|
3358
|
+
issueId: z18.string(),
|
|
3346
3359
|
harness: harnessSchema,
|
|
3347
3360
|
state: runStateSchema,
|
|
3348
|
-
worktree:
|
|
3349
|
-
sessionId:
|
|
3361
|
+
worktree: z18.string().nullable(),
|
|
3362
|
+
sessionId: z18.string().nullable(),
|
|
3350
3363
|
/** Chunks emitted so far (the daemon-local producer sequence). */
|
|
3351
|
-
chunks:
|
|
3352
|
-
error:
|
|
3364
|
+
chunks: z18.number().int().nonnegative(),
|
|
3365
|
+
error: z18.string().nullable(),
|
|
3353
3366
|
/** Set once the run reached a terminal state. */
|
|
3354
3367
|
stopReason: stopReasonSchema.optional(),
|
|
3355
3368
|
/** Lease from the server; the daemon stops the run if it cannot renew it. */
|
|
3356
|
-
leaseExpiresAt:
|
|
3369
|
+
leaseExpiresAt: z18.string().optional(),
|
|
3357
3370
|
/** Last progress seen by the watchdog (ISO time), while the run is active. */
|
|
3358
|
-
lastProgressAt:
|
|
3371
|
+
lastProgressAt: z18.string().optional()
|
|
3359
3372
|
});
|
|
3360
|
-
var daemonStatusSchema =
|
|
3361
|
-
daemonVersion:
|
|
3362
|
-
protocolVersion:
|
|
3363
|
-
pid:
|
|
3364
|
-
dataDir:
|
|
3373
|
+
var daemonStatusSchema = z18.object({
|
|
3374
|
+
daemonVersion: z18.string(),
|
|
3375
|
+
protocolVersion: z18.number().int(),
|
|
3376
|
+
pid: z18.number().int(),
|
|
3377
|
+
dataDir: z18.string(),
|
|
3365
3378
|
/** Null until the device is registered with the server. */
|
|
3366
|
-
deviceId:
|
|
3379
|
+
deviceId: z18.string().nullable(),
|
|
3367
3380
|
/** The workspace the device credential was handed over for, if named. */
|
|
3368
|
-
workspaceId:
|
|
3381
|
+
workspaceId: z18.string().nullable(),
|
|
3369
3382
|
/** Holds a device credential (it may still be refused by the server). */
|
|
3370
|
-
signedIn:
|
|
3371
|
-
server:
|
|
3372
|
-
harnesses:
|
|
3373
|
-
runs:
|
|
3383
|
+
signedIn: z18.boolean(),
|
|
3384
|
+
server: z18.enum(["online", "offline", "unregistered"]),
|
|
3385
|
+
harnesses: z18.array(harnessInfoSchema),
|
|
3386
|
+
runs: z18.array(runSummarySchema),
|
|
3374
3387
|
/** Bytes used by run worktrees under the daemon's data dir. */
|
|
3375
|
-
worktreeDiskBytes:
|
|
3388
|
+
worktreeDiskBytes: z18.number().int().nonnegative(),
|
|
3376
3389
|
/** Items buffered on disk, waiting for the server. */
|
|
3377
|
-
pendingUploads:
|
|
3378
|
-
draining:
|
|
3390
|
+
pendingUploads: z18.number().int().nonnegative(),
|
|
3391
|
+
draining: z18.boolean(),
|
|
3379
3392
|
/** Latest subscription snapshots. Empty when quota polling is off. */
|
|
3380
|
-
quotas:
|
|
3393
|
+
quotas: z18.array(quotaSnapshotSchema).max(6)
|
|
3381
3394
|
});
|
|
3382
|
-
var empty =
|
|
3383
|
-
var ok =
|
|
3395
|
+
var empty = z18.object({}).optional();
|
|
3396
|
+
var ok = z18.object({ ok: z18.literal(true) });
|
|
3384
3397
|
var daemonRpc = {
|
|
3385
3398
|
"daemon.hello": { params: helloParams, result: helloResult },
|
|
3386
3399
|
"daemon.status": { params: empty, result: daemonStatusSchema },
|
|
@@ -3390,10 +3403,10 @@ var daemonRpc = {
|
|
|
3390
3403
|
"daemon.drain": { params: empty, result: ok },
|
|
3391
3404
|
/** Hand the daemon a device credential obtained by the signed-in desktop. */
|
|
3392
3405
|
"device.setCredential": {
|
|
3393
|
-
params:
|
|
3394
|
-
credential:
|
|
3406
|
+
params: z18.object({
|
|
3407
|
+
credential: z18.string().min(1),
|
|
3395
3408
|
/** Needed only for users in more than one workspace. */
|
|
3396
|
-
workspaceId:
|
|
3409
|
+
workspaceId: z18.uuid().optional()
|
|
3397
3410
|
}),
|
|
3398
3411
|
result: ok
|
|
3399
3412
|
},
|
|
@@ -3401,17 +3414,17 @@ var daemonRpc = {
|
|
|
3401
3414
|
"device.clearCredential": { params: empty, result: ok },
|
|
3402
3415
|
/** Claim a queued run pinned to this device and start it. */
|
|
3403
3416
|
"runs.start": {
|
|
3404
|
-
params:
|
|
3417
|
+
params: z18.object({ runId: z18.string() }),
|
|
3405
3418
|
result: runSummarySchema
|
|
3406
3419
|
},
|
|
3407
|
-
"runs.list": { params: empty, result:
|
|
3420
|
+
"runs.list": { params: empty, result: z18.array(runSummarySchema) },
|
|
3408
3421
|
/** Interject a user message into a running session. */
|
|
3409
3422
|
"runs.send": {
|
|
3410
|
-
params:
|
|
3423
|
+
params: z18.object({ runId: z18.string(), text: z18.string().min(1) }),
|
|
3411
3424
|
result: ok
|
|
3412
3425
|
},
|
|
3413
3426
|
"runs.cancel": {
|
|
3414
|
-
params:
|
|
3427
|
+
params: z18.object({ runId: z18.string() }),
|
|
3415
3428
|
result: runSummarySchema
|
|
3416
3429
|
},
|
|
3417
3430
|
/**
|
|
@@ -3419,21 +3432,21 @@ var daemonRpc = {
|
|
|
3419
3432
|
* run on an allow-listed repo without a server. Refused otherwise.
|
|
3420
3433
|
*/
|
|
3421
3434
|
"dev.mockRun": {
|
|
3422
|
-
params:
|
|
3423
|
-
repoId:
|
|
3424
|
-
fixture:
|
|
3425
|
-
baseBranch:
|
|
3435
|
+
params: z18.object({
|
|
3436
|
+
repoId: z18.string(),
|
|
3437
|
+
fixture: z18.string().optional(),
|
|
3438
|
+
baseBranch: z18.string().optional(),
|
|
3426
3439
|
/** Run after the mock submits; defaults to `git diff --check`. */
|
|
3427
|
-
verifyCommand:
|
|
3440
|
+
verifyCommand: z18.string().optional()
|
|
3428
3441
|
}),
|
|
3429
3442
|
result: runSummarySchema
|
|
3430
3443
|
}
|
|
3431
3444
|
};
|
|
3432
3445
|
|
|
3433
3446
|
// ../protocol/src/device.ts
|
|
3434
|
-
import { z as
|
|
3435
|
-
var id3 =
|
|
3436
|
-
var isoTime =
|
|
3447
|
+
import { z as z19 } from "zod";
|
|
3448
|
+
var id3 = z19.string().min(1).max(64);
|
|
3449
|
+
var isoTime = z19.iso.datetime({ offset: true });
|
|
3437
3450
|
var seg = encodeURIComponent;
|
|
3438
3451
|
var DEVICE_ROUTES = {
|
|
3439
3452
|
register: "/v1/devices/register",
|
|
@@ -3459,27 +3472,27 @@ var devicePaths = {
|
|
|
3459
3472
|
runPatch: (runId) => `/v1/runs/${seg(runId)}`,
|
|
3460
3473
|
runCheckpoint: (runId) => `/v1/runs/${seg(runId)}/checkpoint`
|
|
3461
3474
|
};
|
|
3462
|
-
var deviceComputerCapability =
|
|
3463
|
-
var deviceRunnerCapability =
|
|
3464
|
-
os:
|
|
3465
|
-
arch:
|
|
3466
|
-
freeDiskBytes:
|
|
3467
|
-
docker:
|
|
3468
|
-
harnesses:
|
|
3475
|
+
var deviceComputerCapability = z19.object({ installed: z19.boolean(), version: z19.string().max(100).nullable() }).strict();
|
|
3476
|
+
var deviceRunnerCapability = z19.object({
|
|
3477
|
+
os: z19.string().max(50),
|
|
3478
|
+
arch: z19.string().max(50),
|
|
3479
|
+
freeDiskBytes: z19.number().int().nonnegative().nullable(),
|
|
3480
|
+
docker: z19.boolean(),
|
|
3481
|
+
harnesses: z19.array(z19.object({
|
|
3469
3482
|
harness: harnessSchema,
|
|
3470
|
-
state:
|
|
3471
|
-
version:
|
|
3483
|
+
state: z19.enum(["installed", "not_installed", "unsupported"]),
|
|
3484
|
+
version: z19.string().max(100)
|
|
3472
3485
|
})).max(20)
|
|
3473
3486
|
});
|
|
3474
|
-
var deviceRegistration =
|
|
3475
|
-
deviceType:
|
|
3476
|
-
name:
|
|
3477
|
-
hostname:
|
|
3478
|
-
platform:
|
|
3479
|
-
arch:
|
|
3480
|
-
daemonVersion:
|
|
3481
|
-
protocolVersion:
|
|
3482
|
-
harnesses:
|
|
3487
|
+
var deviceRegistration = z19.object({
|
|
3488
|
+
deviceType: z19.enum(["laptop", "server"]).optional(),
|
|
3489
|
+
name: z19.string().trim().min(1).max(200),
|
|
3490
|
+
hostname: z19.string().max(255).nullable().optional(),
|
|
3491
|
+
platform: z19.string().max(50),
|
|
3492
|
+
arch: z19.string().max(50),
|
|
3493
|
+
daemonVersion: z19.string().max(50),
|
|
3494
|
+
protocolVersion: z19.number().int(),
|
|
3495
|
+
harnesses: z19.array(harnessInfoSchema).max(20),
|
|
3483
3496
|
computerUse: deviceComputerCapability.optional(),
|
|
3484
3497
|
runner: deviceRunnerCapability.optional(),
|
|
3485
3498
|
/**
|
|
@@ -3490,115 +3503,115 @@ var deviceRegistration = z18.object({
|
|
|
3490
3503
|
*/
|
|
3491
3504
|
deviceId: id3.optional(),
|
|
3492
3505
|
/** Needed only when the user belongs to more than one workspace. */
|
|
3493
|
-
workspaceId:
|
|
3506
|
+
workspaceId: z19.uuid().optional()
|
|
3494
3507
|
});
|
|
3495
|
-
var deviceRegistered =
|
|
3508
|
+
var deviceRegistered = z19.object({
|
|
3496
3509
|
deviceId: id3,
|
|
3497
|
-
workspaceId:
|
|
3510
|
+
workspaceId: z19.uuid()
|
|
3498
3511
|
});
|
|
3499
|
-
var heartbeatRunSchema =
|
|
3512
|
+
var heartbeatRunSchema = z19.object({
|
|
3500
3513
|
runId: id3,
|
|
3501
3514
|
/** Last tool call, turn boundary or file change (not raw output). */
|
|
3502
3515
|
lastProgressAt: isoTime
|
|
3503
3516
|
});
|
|
3504
|
-
var deviceManagementCommand =
|
|
3505
|
-
var deviceHeartbeatSchema =
|
|
3506
|
-
completedDeviceCommands:
|
|
3507
|
-
failedDeviceCommands:
|
|
3508
|
-
harnesses:
|
|
3517
|
+
var deviceManagementCommand = z19.object({ id: z19.uuid(), kind: z19.enum(["redetect", "restart", "update", "uninstall"]) });
|
|
3518
|
+
var deviceHeartbeatSchema = z19.object({
|
|
3519
|
+
completedDeviceCommands: z19.array(z19.uuid()).max(100).optional(),
|
|
3520
|
+
failedDeviceCommands: z19.array(z19.object({ id: z19.uuid(), error: z19.string().max(500) })).max(100).optional(),
|
|
3521
|
+
harnesses: z19.array(harnessInfoSchema).max(20),
|
|
3509
3522
|
computerUse: deviceComputerCapability.optional(),
|
|
3510
3523
|
runner: deviceRunnerCapability.optional(),
|
|
3511
|
-
deviceType:
|
|
3512
|
-
runs:
|
|
3513
|
-
worktreeDiskBytes:
|
|
3524
|
+
deviceType: z19.enum(["laptop", "server"]).optional(),
|
|
3525
|
+
runs: z19.array(heartbeatRunSchema).max(500),
|
|
3526
|
+
worktreeDiskBytes: z19.number().int().nonnegative(),
|
|
3514
3527
|
/**
|
|
3515
3528
|
* Subscription windows read on this device. Absent when the daemon is not
|
|
3516
3529
|
* polling. Numbers only, never a vendor credential (ADR 0027).
|
|
3517
3530
|
*/
|
|
3518
|
-
quotas:
|
|
3531
|
+
quotas: z19.array(quotaSnapshotSchema).max(6).optional()
|
|
3519
3532
|
});
|
|
3520
|
-
var heartbeatResultSchema =
|
|
3521
|
-
deviceCommands:
|
|
3533
|
+
var heartbeatResultSchema = z19.object({
|
|
3534
|
+
deviceCommands: z19.array(deviceManagementCommand).max(1).optional(),
|
|
3522
3535
|
/** Renewed lease expiry per run id; a run missing here is not renewed. */
|
|
3523
|
-
leases:
|
|
3536
|
+
leases: z19.record(z19.string(), isoTime),
|
|
3524
3537
|
/**
|
|
3525
3538
|
* Runs the device reported that it no longer holds: they ended on the
|
|
3526
3539
|
* server, or went to another attempt after the lease ran out. The daemon
|
|
3527
3540
|
* stops them now instead of when their lease runs out.
|
|
3528
3541
|
*/
|
|
3529
|
-
revoked:
|
|
3542
|
+
revoked: z19.array(id3).max(500).optional(),
|
|
3530
3543
|
/** Short-lived cloud device token, returned only over its authenticated link. */
|
|
3531
|
-
cloudCredential:
|
|
3544
|
+
cloudCredential: z19.string().regex(/^orv_[A-Za-z0-9_-]{43}$/).optional()
|
|
3532
3545
|
});
|
|
3533
3546
|
var RUN_CHECKPOINT_MAX_BYTES = 8 * 1024 * 1024;
|
|
3534
3547
|
var RECOVERY_WORKTREE_HEADER = "x-mikka-recovery-worktree";
|
|
3535
3548
|
var RUN_CHECKPOINT_RECOVERY_MAX_AGE_MS = 30 * 6e4;
|
|
3536
|
-
var runCheckpointSchema =
|
|
3549
|
+
var runCheckpointSchema = z19.object({
|
|
3537
3550
|
/** The commit the run's worktree started from. */
|
|
3538
|
-
baseCommit:
|
|
3551
|
+
baseCommit: z19.string().regex(/^[0-9a-f]{40,64}$/),
|
|
3539
3552
|
/**
|
|
3540
3553
|
* `git diff --binary` from `baseCommit` to the whole worktree (tracked
|
|
3541
3554
|
* and untracked files, ignored ones left out, the agent's own commits
|
|
3542
3555
|
* included), gzipped, base64.
|
|
3543
3556
|
*/
|
|
3544
|
-
patch:
|
|
3557
|
+
patch: z19.string().max(Math.ceil(RUN_CHECKPOINT_MAX_BYTES * 4 / 3) + 4),
|
|
3545
3558
|
/** Files the patch touches. */
|
|
3546
|
-
files:
|
|
3559
|
+
files: z19.number().int().nonnegative(),
|
|
3547
3560
|
takenAt: isoTime,
|
|
3548
3561
|
/** The latest tree could not be checkpointed; it supersedes older patches. */
|
|
3549
|
-
unavailableReason:
|
|
3562
|
+
unavailableReason: z19.literal("too_large").optional()
|
|
3550
3563
|
});
|
|
3551
|
-
var setupRecipeSchema =
|
|
3564
|
+
var setupRecipeSchema = z19.object({
|
|
3552
3565
|
/** Paths relative to the main checkout copied into each new worktree. */
|
|
3553
|
-
copyFiles:
|
|
3566
|
+
copyFiles: z19.array(z19.string().max(1e3)).max(200),
|
|
3554
3567
|
/** Shell command run in the worktree, e.g. `bun install`. */
|
|
3555
|
-
command:
|
|
3568
|
+
command: z19.string().max(2e3).optional(),
|
|
3556
3569
|
/** Approved once per repo by the user; unapproved recipes never run. */
|
|
3557
|
-
approved:
|
|
3570
|
+
approved: z19.boolean()
|
|
3558
3571
|
});
|
|
3559
3572
|
var REPO_ORIGIN_HEADER = "x-mikka-repo-origin-check";
|
|
3560
3573
|
var MODEL_CREDENTIAL_HEADER = "x-mikka-model-credential";
|
|
3561
|
-
var credentialKey =
|
|
3562
|
-
var credentialBaseUrl =
|
|
3574
|
+
var credentialKey = z19.string().min(1).max(4096).refine((value) => !/[\r\n\0]/.test(value));
|
|
3575
|
+
var credentialBaseUrl = z19.url().max(500).refine((value) => {
|
|
3563
3576
|
const url = new URL(value);
|
|
3564
3577
|
return url.protocol === "https:" && !url.username && !url.password && !url.search && !url.hash;
|
|
3565
3578
|
});
|
|
3566
|
-
var runModelCredentialSchema =
|
|
3567
|
-
|
|
3568
|
-
|
|
3579
|
+
var runModelCredentialSchema = z19.discriminatedUnion("kind", [
|
|
3580
|
+
z19.object({ kind: z19.literal("api_key"), key: credentialKey }).strict(),
|
|
3581
|
+
z19.object({ kind: z19.literal("provider"), protocol: z19.enum(["anthropic", "openai"]), baseUrl: credentialBaseUrl, key: credentialKey }).strict()
|
|
3569
3582
|
]);
|
|
3570
|
-
var deviceRepoSchema =
|
|
3583
|
+
var deviceRepoSchema = z19.object({
|
|
3571
3584
|
repoId: id3,
|
|
3572
|
-
name:
|
|
3585
|
+
name: z19.string().max(500),
|
|
3573
3586
|
/** Logical repository key; only trusted cloud runtimes use an absolute path. */
|
|
3574
|
-
path:
|
|
3575
|
-
remoteUrl:
|
|
3587
|
+
path: z19.string().min(1).max(4e3),
|
|
3588
|
+
remoteUrl: z19.string().max(2e3).nullable().optional(),
|
|
3576
3589
|
setup: setupRecipeSchema.optional(),
|
|
3577
3590
|
/** Domains agents may reach in this repo, on top of the harness's own. */
|
|
3578
|
-
networkAllow:
|
|
3591
|
+
networkAllow: z19.array(z19.string().min(1).max(253)).max(200).optional(),
|
|
3579
3592
|
/** Push run branches after a verified hand-in ("always for this repo"). */
|
|
3580
|
-
push:
|
|
3581
|
-
approved:
|
|
3582
|
-
remote:
|
|
3593
|
+
push: z19.object({
|
|
3594
|
+
approved: z19.boolean(),
|
|
3595
|
+
remote: z19.string().min(1).max(200).optional()
|
|
3583
3596
|
}).optional()
|
|
3584
3597
|
});
|
|
3585
|
-
var deviceReposResponse =
|
|
3586
|
-
repos:
|
|
3598
|
+
var deviceReposResponse = z19.object({
|
|
3599
|
+
repos: z19.array(deviceRepoSchema)
|
|
3587
3600
|
});
|
|
3588
|
-
var pendingRunsResponse =
|
|
3601
|
+
var pendingRunsResponse = z19.object({ runIds: z19.array(id3) });
|
|
3589
3602
|
var RUN_KINDS = ["implement", "acceptance", "fix", "plan"];
|
|
3590
|
-
var runAssignmentSchema =
|
|
3603
|
+
var runAssignmentSchema = z19.object({
|
|
3591
3604
|
runId: id3,
|
|
3592
3605
|
issueId: id3,
|
|
3593
3606
|
deviceId: id3,
|
|
3594
3607
|
repoId: id3,
|
|
3595
3608
|
/** Clone URL for local runs; hosted computer assignments keep their isolated workspace. */
|
|
3596
|
-
remoteUrl:
|
|
3609
|
+
remoteUrl: z19.string().min(1).max(4e3).optional(),
|
|
3597
3610
|
/** Absent means origin/HEAD after fetch. */
|
|
3598
|
-
baseBranch:
|
|
3599
|
-
expectedRepoRemote:
|
|
3611
|
+
baseBranch: z19.string().min(1).max(500).optional(),
|
|
3612
|
+
expectedRepoRemote: z19.string().max(2e3).optional(),
|
|
3600
3613
|
harness: harnessSchema,
|
|
3601
|
-
prompt:
|
|
3614
|
+
prompt: z19.string().max(1e5),
|
|
3602
3615
|
/**
|
|
3603
3616
|
* The model the harness's CLI is asked to run, from the per-harness
|
|
3604
3617
|
* preference of the person this run works for (ADR 0060). Absent: the
|
|
@@ -3607,12 +3620,12 @@ var runAssignmentSchema = z18.object({
|
|
|
3607
3620
|
*/
|
|
3608
3621
|
model: modelNameSchema.optional(),
|
|
3609
3622
|
/** Owner-bound selection only; no subscription credential enters the assignment. */
|
|
3610
|
-
subscriptionBinding:
|
|
3611
|
-
bindingId:
|
|
3612
|
-
ownerId:
|
|
3613
|
-
workspaceId:
|
|
3614
|
-
consumerId:
|
|
3615
|
-
route:
|
|
3623
|
+
subscriptionBinding: z19.object({
|
|
3624
|
+
bindingId: z19.uuid(),
|
|
3625
|
+
ownerId: z19.string().min(1).max(128),
|
|
3626
|
+
workspaceId: z19.uuid(),
|
|
3627
|
+
consumerId: z19.uuid(),
|
|
3628
|
+
route: z19.enum(["codex_cli", "claude_code_cli"])
|
|
3616
3629
|
}).strict().optional(),
|
|
3617
3630
|
/**
|
|
3618
3631
|
* The run's own API key, opened for this claim only. Never with
|
|
@@ -3621,34 +3634,34 @@ var runAssignmentSchema = z18.object({
|
|
|
3621
3634
|
*/
|
|
3622
3635
|
modelCredential: runModelCredentialSchema.optional(),
|
|
3623
3636
|
/** Local host authority comes only from the server's owner-bound Bot run. */
|
|
3624
|
-
localComputer:
|
|
3625
|
-
botId:
|
|
3626
|
-
ownerId:
|
|
3627
|
-
workspaceId:
|
|
3628
|
-
policyVersion:
|
|
3629
|
-
permission:
|
|
3637
|
+
localComputer: z19.object({
|
|
3638
|
+
botId: z19.uuid(),
|
|
3639
|
+
ownerId: z19.string().min(1).max(128),
|
|
3640
|
+
workspaceId: z19.uuid(),
|
|
3641
|
+
policyVersion: z19.number().int().nonnegative().max(2147483647),
|
|
3642
|
+
permission: z19.enum(["allow", "ask"])
|
|
3630
3643
|
}).strict().optional(),
|
|
3631
3644
|
/** Trusted server assignment; the model cannot choose a Bot or display. */
|
|
3632
|
-
computer:
|
|
3633
|
-
botId:
|
|
3634
|
-
ownerId:
|
|
3635
|
-
display:
|
|
3636
|
-
policyVersion:
|
|
3645
|
+
computer: z19.object({
|
|
3646
|
+
botId: z19.uuid(),
|
|
3647
|
+
ownerId: z19.string().min(1).max(128),
|
|
3648
|
+
display: z19.string().regex(/^:[1-9][0-9]{0,2}$/),
|
|
3649
|
+
policyVersion: z19.number().int().nonnegative().max(2147483647)
|
|
3637
3650
|
}).strict().optional(),
|
|
3638
3651
|
/**
|
|
3639
3652
|
* 4e3: the task's explicit user variables (workspace + matching repository secrets/env, NAME -> value).
|
|
3640
3653
|
* Cloud workers only. Passed into the task container through its own channel, never into the worker's
|
|
3641
3654
|
* env, and never written to the run journal.
|
|
3642
3655
|
*/
|
|
3643
|
-
taskEnv:
|
|
3656
|
+
taskEnv: z19.record(z19.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/), z19.string().max(65536)).optional(),
|
|
3644
3657
|
/**
|
|
3645
3658
|
* Names in `taskEnv` that are secrets (kind 'secret'; env vars are not listed). The daemon masks
|
|
3646
3659
|
* their values (raw + standard base64) in run output before anything is uploaded; the server
|
|
3647
3660
|
* masks again. Older daemons strip this field and rely on server-side masking only.
|
|
3648
3661
|
*/
|
|
3649
|
-
taskSecretNames:
|
|
3662
|
+
taskSecretNames: z19.array(z19.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/)).max(500).optional(),
|
|
3650
3663
|
/** Mock harness only: fixture name under `packages/daemon/fixtures`. */
|
|
3651
|
-
fixture:
|
|
3664
|
+
fixture: z19.string().max(200).optional(),
|
|
3652
3665
|
/**
|
|
3653
3666
|
* The issue's branch (`mikka/<team>-<number>`, ADR 0024): every run of
|
|
3654
3667
|
* the issue pushes its verified commit here, so one pull request follows
|
|
@@ -3656,9 +3669,9 @@ var runAssignmentSchema = z18.object({
|
|
|
3656
3669
|
* this branch from the remote when it exists. Without it the daemon
|
|
3657
3670
|
* pushes the run's own branch.
|
|
3658
3671
|
*/
|
|
3659
|
-
pushBranch:
|
|
3672
|
+
pushBranch: z19.string().min(1).max(250).optional(),
|
|
3660
3673
|
/** Run by the daemon in the worktree after the agent submits. */
|
|
3661
|
-
verifyCommand:
|
|
3674
|
+
verifyCommand: z19.string().max(2e3).optional(),
|
|
3662
3675
|
/** Run lease; renewed through the device heartbeat. */
|
|
3663
3676
|
leaseExpiresAt: isoTime.optional(),
|
|
3664
3677
|
/**
|
|
@@ -3667,25 +3680,25 @@ var runAssignmentSchema = z18.object({
|
|
|
3667
3680
|
* it stops working when the run ends. Absent: the server could not issue
|
|
3668
3681
|
* one, and the run goes ahead without it.
|
|
3669
3682
|
*/
|
|
3670
|
-
mcp:
|
|
3671
|
-
url:
|
|
3672
|
-
token:
|
|
3673
|
-
mailbox:
|
|
3683
|
+
mcp: z19.object({
|
|
3684
|
+
url: z19.url(),
|
|
3685
|
+
token: z19.string().min(1).max(200),
|
|
3686
|
+
mailbox: z19.literal(true).optional(),
|
|
3674
3687
|
/** Apps (Composio toolkits) this run may use through the Mikka server, one MCP entry each. */
|
|
3675
|
-
apps:
|
|
3688
|
+
apps: z19.array(z19.string().regex(/^[a-z][a-z0-9_]{0,63}$/)).max(64).optional()
|
|
3676
3689
|
}).optional(),
|
|
3677
3690
|
/** Agent-owned GitHub delivery; the same run token exchanges short-lived credentials. */
|
|
3678
|
-
github:
|
|
3679
|
-
endpoint:
|
|
3680
|
-
repository:
|
|
3681
|
-
branch:
|
|
3691
|
+
github: z19.object({
|
|
3692
|
+
endpoint: z19.url(),
|
|
3693
|
+
repository: z19.string().regex(/^[a-z0-9_.-]+\/[a-z0-9_.-]+$/),
|
|
3694
|
+
branch: z19.string().regex(/^mikka\/[a-z0-9-]+-[1-9][0-9]*$/)
|
|
3682
3695
|
}).strict().optional(),
|
|
3683
3696
|
/** Question continuation must not silently open a different session. */
|
|
3684
3697
|
/**
|
|
3685
3698
|
* What the orchestrator dispatched this run for (ADR 0023). `plan` writes a
|
|
3686
3699
|
* spec and proposes a split instead of changing code (ADR ORV-205).
|
|
3687
3700
|
*/
|
|
3688
|
-
kind:
|
|
3701
|
+
kind: z19.enum(RUN_KINDS).optional(),
|
|
3689
3702
|
/**
|
|
3690
3703
|
* The earlier run this one continues (continue, fix, answer, a person's
|
|
3691
3704
|
* message): the daemon works on in that run's worktree, on this run's
|
|
@@ -3693,7 +3706,7 @@ var runAssignmentSchema = z18.object({
|
|
|
3693
3706
|
*/
|
|
3694
3707
|
continuesRunId: id3.optional(),
|
|
3695
3708
|
/** A same-device retry with no usable snapshot must reuse its real worktree. */
|
|
3696
|
-
requireWorktreeContinuation:
|
|
3709
|
+
requireWorktreeContinuation: z19.literal(true).optional(),
|
|
3697
3710
|
/**
|
|
3698
3711
|
* The latest checkpoint of the attempt this run takes over after its
|
|
3699
3712
|
* machine went offline. Used only for a new worktree (another machine, or
|
|
@@ -3706,25 +3719,25 @@ var runAssignmentSchema = z18.object({
|
|
|
3706
3719
|
* The harness session to continue. A daemon that cannot resume starts a
|
|
3707
3720
|
* new session with `prompt`, which always carries the full brief.
|
|
3708
3721
|
*/
|
|
3709
|
-
resumeSessionId:
|
|
3710
|
-
requireSessionResume:
|
|
3711
|
-
preserveQuestionWorktree:
|
|
3712
|
-
questionId:
|
|
3722
|
+
resumeSessionId: z19.string().max(500).optional(),
|
|
3723
|
+
requireSessionResume: z19.boolean().optional(),
|
|
3724
|
+
preserveQuestionWorktree: z19.boolean().optional(),
|
|
3725
|
+
questionId: z19.uuid().optional(),
|
|
3713
3726
|
/**
|
|
3714
3727
|
* What this run adds on top of the brief (a person's message, an answer,
|
|
3715
3728
|
* a fix request). A resumed session gets only this as its next message;
|
|
3716
3729
|
* a new session gets `prompt`, which already includes it.
|
|
3717
3730
|
*/
|
|
3718
|
-
followUp:
|
|
3731
|
+
followUp: z19.string().max(1e5).optional(),
|
|
3719
3732
|
/**
|
|
3720
3733
|
* The workspace's agent permissions and network allow-list (ADR 0028).
|
|
3721
3734
|
* Absent from an older server: the daemon applies the ADR 0009 defaults.
|
|
3722
3735
|
*/
|
|
3723
3736
|
policy: runPolicySchema.optional(),
|
|
3724
3737
|
/** Trusted server revision for the exact run policy; older servers omit it. */
|
|
3725
|
-
policyRevision:
|
|
3738
|
+
policyRevision: z19.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
3726
3739
|
/** Only a trusted server context can make a snapshot required. */
|
|
3727
|
-
policySnapshotRequired:
|
|
3740
|
+
policySnapshotRequired: z19.boolean().optional(),
|
|
3728
3741
|
policySnapshot: signedPolicySnapshotSchema.optional(),
|
|
3729
3742
|
/**
|
|
3730
3743
|
* The skills mounted on this run's agent and still enabled, resolved at
|
|
@@ -3732,14 +3745,14 @@ var runAssignmentSchema = z18.object({
|
|
|
3732
3745
|
* brief and writes them under the run's directory. Absent from an older
|
|
3733
3746
|
* server: the run simply has none.
|
|
3734
3747
|
*/
|
|
3735
|
-
skills:
|
|
3748
|
+
skills: z19.array(runSkillSchema).max(MAX_SKILLS_PER_RUN).optional(),
|
|
3736
3749
|
/** Server-minted assignment provenance; does not grant any policy permission. */
|
|
3737
3750
|
skillReceipt: skillAssignmentReceiptSchema.optional(),
|
|
3738
3751
|
/** Frozen by the server benchmark ledger; never extracted from model output. */
|
|
3739
3752
|
benchmark: runBenchmarkContext.optional()
|
|
3740
3753
|
}).refine((value) => !(value.modelCredential && value.subscriptionBinding), { message: "A run has one model credential", path: ["modelCredential"] });
|
|
3741
|
-
var runPatchSchema =
|
|
3742
|
-
state:
|
|
3754
|
+
var runPatchSchema = z19.object({
|
|
3755
|
+
state: z19.enum([
|
|
3743
3756
|
"queued",
|
|
3744
3757
|
"preparing",
|
|
3745
3758
|
"running",
|
|
@@ -3750,70 +3763,80 @@ var runPatchSchema = z18.object({
|
|
|
3750
3763
|
"failed",
|
|
3751
3764
|
"cancelled"
|
|
3752
3765
|
]),
|
|
3753
|
-
sessionId:
|
|
3754
|
-
worktree:
|
|
3755
|
-
error:
|
|
3766
|
+
sessionId: z19.string().max(500).nullable().optional(),
|
|
3767
|
+
worktree: z19.string().max(4e3).nullable().optional(),
|
|
3768
|
+
error: z19.string().max(1e4).nullable().optional(),
|
|
3756
3769
|
/** Set on every terminal state. */
|
|
3757
3770
|
stopReason: runStopReason.optional()
|
|
3758
3771
|
});
|
|
3759
|
-
var runEventBatchSchema =
|
|
3760
|
-
fromSeq:
|
|
3761
|
-
chunks:
|
|
3772
|
+
var runEventBatchSchema = z19.object({
|
|
3773
|
+
fromSeq: z19.number().int().min(1),
|
|
3774
|
+
chunks: z19.array(z19.looseObject({ type: z19.string() })).min(1).max(1e3)
|
|
3762
3775
|
});
|
|
3763
|
-
var runEventsAccepted =
|
|
3776
|
+
var runEventsAccepted = z19.object({
|
|
3764
3777
|
/** Producer seq of the last chunk the server holds for this run. */
|
|
3765
|
-
offset:
|
|
3778
|
+
offset: z19.string()
|
|
3766
3779
|
});
|
|
3767
3780
|
var COMMANDS_SKIP_PARAM = "skip";
|
|
3768
|
-
var
|
|
3769
|
-
|
|
3770
|
-
|
|
3781
|
+
var MAILBOX_NOTICE_HEADER = "x-mikka-mailbox-notices";
|
|
3782
|
+
var runCommandSchema = z19.discriminatedUnion("kind", [
|
|
3783
|
+
z19.object({
|
|
3784
|
+
kind: z19.literal("input"),
|
|
3771
3785
|
runId: id3,
|
|
3772
|
-
messageId:
|
|
3773
|
-
text:
|
|
3786
|
+
messageId: z19.uuid(),
|
|
3787
|
+
text: z19.string().min(1).max(1e5)
|
|
3774
3788
|
}),
|
|
3775
|
-
|
|
3789
|
+
z19.object({ kind: z19.literal("stop"), runId: id3 }),
|
|
3790
|
+
// A host notification carries addresses only; peer content remains behind
|
|
3791
|
+
// the authenticated mailbox read and retains its original provenance.
|
|
3792
|
+
z19.object({ kind: z19.literal("mailbox_notice"), runId: id3, messageIds: z19.array(z19.uuid()).min(1).max(50) })
|
|
3776
3793
|
]);
|
|
3777
|
-
var runCommandsResponse =
|
|
3778
|
-
commands:
|
|
3794
|
+
var runCommandsResponse = z19.object({
|
|
3795
|
+
commands: z19.array(runCommandSchema).max(500),
|
|
3796
|
+
/**
|
|
3797
|
+
* Runs queued for this device (outside `skip`), so it claims them now
|
|
3798
|
+
* instead of on its next heartbeat. A queued run also ends the long-poll.
|
|
3799
|
+
* Absent from older servers; the heartbeat still claims either way.
|
|
3800
|
+
*/
|
|
3801
|
+
queuedRuns: z19.array(id3).max(100).optional()
|
|
3779
3802
|
});
|
|
3780
|
-
var runCommandsAck =
|
|
3781
|
-
delivered:
|
|
3803
|
+
var runCommandsAck = z19.object({
|
|
3804
|
+
delivered: z19.array(z19.uuid()).max(500)
|
|
3782
3805
|
});
|
|
3783
3806
|
var FS_MAX_ENTRIES = 500;
|
|
3784
|
-
var fsBrowseRequest =
|
|
3807
|
+
var fsBrowseRequest = z19.object({
|
|
3785
3808
|
/** Absolute path on the device; omitted: the device's home folder. */
|
|
3786
|
-
path:
|
|
3787
|
-
showHidden:
|
|
3809
|
+
path: z19.string().trim().min(1).max(4e3).optional(),
|
|
3810
|
+
showHidden: z19.boolean().optional()
|
|
3788
3811
|
});
|
|
3789
|
-
var fsPendingRequest = fsBrowseRequest.extend({ id:
|
|
3790
|
-
var fsRequestsResponse =
|
|
3791
|
-
requests:
|
|
3812
|
+
var fsPendingRequest = fsBrowseRequest.extend({ id: z19.uuid() });
|
|
3813
|
+
var fsRequestsResponse = z19.object({
|
|
3814
|
+
requests: z19.array(fsPendingRequest).max(50)
|
|
3792
3815
|
});
|
|
3793
|
-
var fsEntry =
|
|
3794
|
-
name:
|
|
3795
|
-
path:
|
|
3816
|
+
var fsEntry = z19.object({
|
|
3817
|
+
name: z19.string().max(1e3),
|
|
3818
|
+
path: z19.string().max(4e3),
|
|
3796
3819
|
/** The folder is the top level of a git repo (it has a `.git`). */
|
|
3797
|
-
isRepo:
|
|
3820
|
+
isRepo: z19.boolean()
|
|
3798
3821
|
});
|
|
3799
|
-
var fsListing =
|
|
3800
|
-
ok:
|
|
3801
|
-
path:
|
|
3822
|
+
var fsListing = z19.object({
|
|
3823
|
+
ok: z19.literal(true),
|
|
3824
|
+
path: z19.string().max(4e3),
|
|
3802
3825
|
/** Null at the filesystem root. */
|
|
3803
|
-
parent:
|
|
3804
|
-
home:
|
|
3826
|
+
parent: z19.string().max(4e3).nullable(),
|
|
3827
|
+
home: z19.string().max(4e3),
|
|
3805
3828
|
/** `darwin`, `linux`, `win32`: for path separators and wording. */
|
|
3806
|
-
platform:
|
|
3807
|
-
entries:
|
|
3829
|
+
platform: z19.string().max(50),
|
|
3830
|
+
entries: z19.array(fsEntry).max(FS_MAX_ENTRIES),
|
|
3808
3831
|
/** More folders existed than `FS_MAX_ENTRIES`. */
|
|
3809
|
-
truncated:
|
|
3832
|
+
truncated: z19.boolean(),
|
|
3810
3833
|
/**
|
|
3811
3834
|
* The git repo `path` is in, if any: its top level and `origin` (or the
|
|
3812
3835
|
* first remote). This is what `device.addRepo` should be given.
|
|
3813
3836
|
*/
|
|
3814
|
-
repo:
|
|
3815
|
-
path:
|
|
3816
|
-
remoteUrl:
|
|
3837
|
+
repo: z19.object({
|
|
3838
|
+
path: z19.string().max(4e3),
|
|
3839
|
+
remoteUrl: z19.string().max(2e3).nullable()
|
|
3817
3840
|
}).nullable()
|
|
3818
3841
|
});
|
|
3819
3842
|
var FS_ERROR_CODES = [
|
|
@@ -3822,12 +3845,12 @@ var FS_ERROR_CODES = [
|
|
|
3822
3845
|
"denied",
|
|
3823
3846
|
"failed"
|
|
3824
3847
|
];
|
|
3825
|
-
var fsFailure =
|
|
3826
|
-
ok:
|
|
3827
|
-
code:
|
|
3828
|
-
message:
|
|
3848
|
+
var fsFailure = z19.object({
|
|
3849
|
+
ok: z19.literal(false),
|
|
3850
|
+
code: z19.enum(FS_ERROR_CODES),
|
|
3851
|
+
message: z19.string().max(1e3)
|
|
3829
3852
|
});
|
|
3830
|
-
var fsResult =
|
|
3853
|
+
var fsResult = z19.discriminatedUnion("ok", [fsListing, fsFailure]);
|
|
3831
3854
|
var fsPaths = {
|
|
3832
3855
|
browse: (deviceId) => `/v1/devices/${seg(deviceId)}/fs/browse`,
|
|
3833
3856
|
requests: (deviceId, waitSeconds) => `/v1/devices/${seg(deviceId)}/fs/requests?wait=${waitSeconds}`,
|
|
@@ -3835,38 +3858,38 @@ var fsPaths = {
|
|
|
3835
3858
|
};
|
|
3836
3859
|
|
|
3837
3860
|
// ../protocol/src/orchestrator.ts
|
|
3838
|
-
import { z as
|
|
3861
|
+
import { z as z20 } from "zod";
|
|
3839
3862
|
var minutes = (n) => n * 6e4;
|
|
3840
|
-
var orchestratorSettingsSchema =
|
|
3863
|
+
var orchestratorSettingsSchema = z20.object({
|
|
3841
3864
|
/** "Continue" prompts after a turn ended without a submit. */
|
|
3842
|
-
maxContinuations:
|
|
3865
|
+
maxContinuations: z20.number().int().min(0).max(20).default(3),
|
|
3843
3866
|
/** Resumes after the CLI crashed, before one fresh session. */
|
|
3844
|
-
maxCrashRetries:
|
|
3867
|
+
maxCrashRetries: z20.number().int().min(0).max(20).default(3),
|
|
3845
3868
|
/** Fix rounds after the daemon's verify failed. */
|
|
3846
|
-
maxFixAttempts:
|
|
3869
|
+
maxFixAttempts: z20.number().int().min(0).max(20).default(3),
|
|
3847
3870
|
/** "You seem stuck" prompts after a run stalled. */
|
|
3848
|
-
maxStallRecoveries:
|
|
3871
|
+
maxStallRecoveries: z20.number().int().min(0).max(20).default(2),
|
|
3849
3872
|
/** No progress for this long while the lease is fresh = stalled. */
|
|
3850
|
-
stalledAfterMs:
|
|
3873
|
+
stalledAfterMs: z20.number().int().min(minutes(1)).default(minutes(10)),
|
|
3851
3874
|
/** A device offline this long is handed to a person (no auto switch). */
|
|
3852
|
-
deviceOfflineEscalateMs:
|
|
3875
|
+
deviceOfflineEscalateMs: z20.number().int().min(0).default(minutes(30)),
|
|
3853
3876
|
/** An unanswered question frees its concurrency slot after this. */
|
|
3854
|
-
questionSlotReleaseMs:
|
|
3877
|
+
questionSlotReleaseMs: z20.number().int().min(0).default(minutes(24 * 60)),
|
|
3855
3878
|
/** Automatic dispatches per issue per hour before a person looks. */
|
|
3856
|
-
maxDispatchesPerHour:
|
|
3879
|
+
maxDispatchesPerHour: z20.number().int().min(1).max(100).default(6),
|
|
3857
3880
|
/** Wait before resuming a run that hit its quota (no reset time known). */
|
|
3858
|
-
quotaBackoffMs:
|
|
3881
|
+
quotaBackoffMs: z20.number().int().min(0).default(minutes(15)),
|
|
3859
3882
|
/**
|
|
3860
3883
|
* How often an issue waiting on its pull request or CI asks GitHub again
|
|
3861
3884
|
* when no webhook arrived (ADR 0024).
|
|
3862
3885
|
*/
|
|
3863
|
-
ciRecheckMs:
|
|
3886
|
+
ciRecheckMs: z20.number().int().min(3e4).default(minutes(2)),
|
|
3864
3887
|
/** A pushed commit with no checks after this long has no CI: it passes. */
|
|
3865
|
-
ciNoChecksMs:
|
|
3888
|
+
ciNoChecksMs: z20.number().int().min(0).default(minutes(5)),
|
|
3866
3889
|
/** CI still running after this long goes to a person. */
|
|
3867
|
-
ciTimeoutMs:
|
|
3890
|
+
ciTimeoutMs: z20.number().int().min(minutes(5)).default(minutes(120)),
|
|
3868
3891
|
/** Remote URL of the repo this project's issues run in. */
|
|
3869
|
-
repoUrl:
|
|
3892
|
+
repoUrl: z20.string().max(2e3).optional()
|
|
3870
3893
|
});
|
|
3871
3894
|
var CRASH_BACKOFF_MS = [1e4, 6e4, minutes(5)];
|
|
3872
3895
|
var UPSTREAM_RECHECK_MS = minutes(5);
|
|
@@ -3910,30 +3933,30 @@ var WAIT_DETAIL_CODES = [
|
|
|
3910
3933
|
...PERSON_WAIT_DETAIL_CODES,
|
|
3911
3934
|
...EXTERNAL_WAIT_DETAIL_CODES
|
|
3912
3935
|
];
|
|
3913
|
-
var waitDetailSchema =
|
|
3914
|
-
code:
|
|
3915
|
-
params:
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3936
|
+
var waitDetailSchema = z20.object({
|
|
3937
|
+
code: z20.enum(WAIT_DETAIL_CODES),
|
|
3938
|
+
params: z20.record(
|
|
3939
|
+
z20.string(),
|
|
3940
|
+
z20.union([
|
|
3941
|
+
z20.string(),
|
|
3942
|
+
z20.number(),
|
|
3943
|
+
z20.array(z20.string()),
|
|
3921
3944
|
// `repo_ambiguous`: the repos a person can pick from.
|
|
3922
|
-
|
|
3945
|
+
z20.array(z20.record(z20.string(), z20.string()))
|
|
3923
3946
|
])
|
|
3924
3947
|
).optional()
|
|
3925
3948
|
});
|
|
3926
|
-
var prChecksSchema =
|
|
3927
|
-
state:
|
|
3949
|
+
var prChecksSchema = z20.object({
|
|
3950
|
+
state: z20.enum(["pending", "success", "failure", "none"]),
|
|
3928
3951
|
/** Failed checks, for the fix round's brief and the issue page. */
|
|
3929
|
-
failing:
|
|
3930
|
-
|
|
3931
|
-
name:
|
|
3932
|
-
summary:
|
|
3933
|
-
url:
|
|
3952
|
+
failing: z20.array(
|
|
3953
|
+
z20.object({
|
|
3954
|
+
name: z20.string().max(500),
|
|
3955
|
+
summary: z20.string().max(4e3).optional(),
|
|
3956
|
+
url: z20.string().max(2e3).optional()
|
|
3934
3957
|
})
|
|
3935
3958
|
).max(50),
|
|
3936
|
-
total:
|
|
3959
|
+
total: z20.number().int().min(0)
|
|
3937
3960
|
});
|
|
3938
3961
|
var DEFAULT_BRANCH_TEMPLATE = "mikka/{team}-{number}";
|
|
3939
3962
|
var BRANCH_FORBIDDEN = /[\s~^:?*[\\]|\.\.|@\{|\/\/|^\/|\/$/;
|
|
@@ -3942,29 +3965,29 @@ var hasControlCharacter = (value) => [...value].some((char) => {
|
|
|
3942
3965
|
const code = char.charCodeAt(0);
|
|
3943
3966
|
return code < 32 || code === 127;
|
|
3944
3967
|
});
|
|
3945
|
-
var branchTemplateSchema =
|
|
3968
|
+
var branchTemplateSchema = z20.string().trim().min(1).max(200).refine((value) => value.includes("{number}"), {
|
|
3946
3969
|
message: "The template must contain {number}."
|
|
3947
3970
|
}).refine(
|
|
3948
3971
|
(value) => !BRANCH_FORBIDDEN.test(value) && !hasControlCharacter(value),
|
|
3949
3972
|
{ message: BRANCH_FORBIDDEN_HINT }
|
|
3950
3973
|
);
|
|
3951
|
-
var prBodyTemplateSchema =
|
|
3974
|
+
var prBodyTemplateSchema = z20.string().max(2e4).nullable().optional();
|
|
3952
3975
|
var REVIEW_CHECK_HARNESSES = [
|
|
3953
3976
|
"claude_code",
|
|
3954
3977
|
"codex",
|
|
3955
3978
|
"cursor"
|
|
3956
3979
|
];
|
|
3957
|
-
var reviewRuleSchema =
|
|
3980
|
+
var reviewRuleSchema = z20.object({
|
|
3958
3981
|
/** In Review needs an open pull request for the issue's branch (ADR 0024). */
|
|
3959
|
-
requirePullRequest:
|
|
3982
|
+
requirePullRequest: z20.boolean().default(true),
|
|
3960
3983
|
/** ... and green CI on it. Ignored when no pull request is required. */
|
|
3961
|
-
requireCi:
|
|
3984
|
+
requireCi: z20.boolean().default(true),
|
|
3962
3985
|
/**
|
|
3963
3986
|
* The harness that must run the read-only check (ADR 0046). Null: any
|
|
3964
3987
|
* second agent on the device. A configured harness the device does not run
|
|
3965
3988
|
* means no check runs, exactly as if the device had no second agent.
|
|
3966
3989
|
*/
|
|
3967
|
-
checkHarness:
|
|
3990
|
+
checkHarness: z20.enum(REVIEW_CHECK_HARNESSES).nullable().default(null),
|
|
3968
3991
|
branchTemplate: branchTemplateSchema.default(DEFAULT_BRANCH_TEMPLATE),
|
|
3969
3992
|
/** `{key}`, `{title}` and `{summary}`; null keeps Mikka's default text. */
|
|
3970
3993
|
prBodyTemplate: prBodyTemplateSchema.default(null)
|
|
@@ -3989,9 +4012,9 @@ var WEB_PLATFORM = Object.freeze({
|
|
|
3989
4012
|
});
|
|
3990
4013
|
|
|
3991
4014
|
// ../protocol/src/preview.ts
|
|
3992
|
-
import { z as
|
|
4015
|
+
import { z as z21 } from "zod";
|
|
3993
4016
|
var PREVIEW_MAX_LENGTH = 5 * 1024 * 1024;
|
|
3994
|
-
var previewHtml =
|
|
4017
|
+
var previewHtml = z21.string().max(PREVIEW_MAX_LENGTH);
|
|
3995
4018
|
var DIRECTIVES = [
|
|
3996
4019
|
"default-src 'none'",
|
|
3997
4020
|
"script-src 'unsafe-inline'",
|
|
@@ -4008,13 +4031,13 @@ var PREVIEW_CSP_HEADER = ["sandbox allow-scripts", ...DIRECTIVES].join(
|
|
|
4008
4031
|
var META = `<meta http-equiv="Content-Security-Policy" content="${DIRECTIVES.join("; ")}">`;
|
|
4009
4032
|
|
|
4010
4033
|
// ../protocol/src/profile.ts
|
|
4011
|
-
import { z as
|
|
4012
|
-
var usernameSchema =
|
|
4034
|
+
import { z as z22 } from "zod";
|
|
4035
|
+
var usernameSchema = z22.string().trim().min(3, "At least 3 characters.").max(32, "At most 32 characters.").regex(
|
|
4013
4036
|
/^[a-z0-9][a-z0-9_-]*$/,
|
|
4014
4037
|
"Start with a letter or digit; lowercase letters, digits, - and _ only."
|
|
4015
4038
|
);
|
|
4016
|
-
var displayNameSchema =
|
|
4017
|
-
var avatarUrlSchema =
|
|
4039
|
+
var displayNameSchema = z22.string().trim().min(1, "A name is required.").max(80, "At most 80 characters.");
|
|
4040
|
+
var avatarUrlSchema = z22.url().max(2048).refine((value) => /^https?:\/\//.test(value), "Use an http(s) URL.");
|
|
4018
4041
|
var AVATAR_MAX_BYTES = 5 * 1024 * 1024;
|
|
4019
4042
|
var AVATAR_CONTENT_TYPES = [
|
|
4020
4043
|
"image/png",
|
|
@@ -4022,16 +4045,16 @@ var AVATAR_CONTENT_TYPES = [
|
|
|
4022
4045
|
"image/webp",
|
|
4023
4046
|
"image/gif"
|
|
4024
4047
|
];
|
|
4025
|
-
var avatarPresignRequest =
|
|
4026
|
-
contentType:
|
|
4048
|
+
var avatarPresignRequest = z22.object({
|
|
4049
|
+
contentType: z22.enum(AVATAR_CONTENT_TYPES),
|
|
4027
4050
|
/** Bytes, checked against AVATAR_MAX_BYTES. */
|
|
4028
|
-
size:
|
|
4051
|
+
size: z22.number().int().positive()
|
|
4029
4052
|
});
|
|
4030
|
-
var avatarPresignResponse =
|
|
4031
|
-
uploadUrl:
|
|
4053
|
+
var avatarPresignResponse = z22.object({
|
|
4054
|
+
uploadUrl: z22.url(),
|
|
4032
4055
|
/** What to store in `user.image` once the PUT has succeeded. */
|
|
4033
4056
|
publicUrl: avatarUrlSchema,
|
|
4034
|
-
expiresIn:
|
|
4057
|
+
expiresIn: z22.number().int().positive()
|
|
4035
4058
|
});
|
|
4036
4059
|
|
|
4037
4060
|
// ../protocol/src/relay.ts
|
|
@@ -4040,31 +4063,31 @@ import {
|
|
|
4040
4063
|
safeValidateUIMessages,
|
|
4041
4064
|
uiMessageChunkSchema
|
|
4042
4065
|
} from "ai";
|
|
4043
|
-
import { z as
|
|
4066
|
+
import { z as z23 } from "zod";
|
|
4044
4067
|
var RELAY_PROTOCOL_VERSION = 1;
|
|
4045
4068
|
var MAX_INPUT_LENGTH = 2e4;
|
|
4046
|
-
var uuid =
|
|
4047
|
-
var runEvent =
|
|
4069
|
+
var uuid = z23.uuid();
|
|
4070
|
+
var runEvent = z23.discriminatedUnion("kind", [
|
|
4048
4071
|
/** One streaming chunk of the unfinished message `messageId`. */
|
|
4049
|
-
|
|
4050
|
-
kind:
|
|
4072
|
+
z23.object({
|
|
4073
|
+
kind: z23.literal("chunk"),
|
|
4051
4074
|
messageId: uuid,
|
|
4052
|
-
chunk:
|
|
4075
|
+
chunk: z23.looseObject({ type: z23.string() })
|
|
4053
4076
|
}),
|
|
4054
4077
|
/** A finished message; persisted as a `message` row, then fanned out. */
|
|
4055
|
-
|
|
4056
|
-
kind:
|
|
4078
|
+
z23.object({
|
|
4079
|
+
kind: z23.literal("message.final"),
|
|
4057
4080
|
/** Order of the message within the run. */
|
|
4058
|
-
seq:
|
|
4059
|
-
message:
|
|
4081
|
+
seq: z23.number().int().min(0),
|
|
4082
|
+
message: z23.looseObject({
|
|
4060
4083
|
id: uuid,
|
|
4061
|
-
role:
|
|
4062
|
-
parts:
|
|
4084
|
+
role: z23.enum(["system", "user", "assistant"]),
|
|
4085
|
+
parts: z23.array(z23.looseObject({ type: z23.string() }))
|
|
4063
4086
|
})
|
|
4064
4087
|
}),
|
|
4065
|
-
|
|
4066
|
-
kind:
|
|
4067
|
-
status:
|
|
4088
|
+
z23.object({
|
|
4089
|
+
kind: z23.literal("run.status"),
|
|
4090
|
+
status: z23.enum([
|
|
4068
4091
|
"queued",
|
|
4069
4092
|
"preparing",
|
|
4070
4093
|
"running",
|
|
@@ -4077,48 +4100,48 @@ var runEvent = z22.discriminatedUnion("kind", [
|
|
|
4077
4100
|
})
|
|
4078
4101
|
]);
|
|
4079
4102
|
var chunkSchema = asSchema(uiMessageChunkSchema);
|
|
4080
|
-
var v =
|
|
4081
|
-
var presenceView =
|
|
4082
|
-
|
|
4083
|
-
|
|
4103
|
+
var v = z23.literal(RELAY_PROTOCOL_VERSION);
|
|
4104
|
+
var presenceView = z23.discriminatedUnion("type", [
|
|
4105
|
+
z23.object({ type: z23.literal("issue"), id: uuid }),
|
|
4106
|
+
z23.object({ type: z23.literal("project"), id: uuid })
|
|
4084
4107
|
]);
|
|
4085
|
-
var relayClientMessage =
|
|
4086
|
-
|
|
4108
|
+
var relayClientMessage = z23.discriminatedUnion("type", [
|
|
4109
|
+
z23.object({
|
|
4087
4110
|
v,
|
|
4088
|
-
type:
|
|
4111
|
+
type: z23.literal("subscribe"),
|
|
4089
4112
|
runId: uuid,
|
|
4090
4113
|
/** Resume after this seq; omitted = everything still buffered. */
|
|
4091
|
-
after:
|
|
4114
|
+
after: z23.number().int().min(0).optional()
|
|
4092
4115
|
}),
|
|
4093
|
-
|
|
4094
|
-
|
|
4116
|
+
z23.object({ v, type: z23.literal("unsubscribe"), runId: uuid }),
|
|
4117
|
+
z23.object({ v, type: z23.literal("publish"), runId: uuid, event: runEvent }),
|
|
4095
4118
|
/**
|
|
4096
4119
|
* A person's message to the running agent (ADR 0018). Saved as a `user`
|
|
4097
4120
|
* message row with this id (a re-send with the same id is applied once),
|
|
4098
4121
|
* then handed to the run's daemon, which marks it delivered.
|
|
4099
4122
|
*/
|
|
4100
|
-
|
|
4123
|
+
z23.object({
|
|
4101
4124
|
v,
|
|
4102
|
-
type:
|
|
4125
|
+
type: z23.literal("send"),
|
|
4103
4126
|
runId: uuid,
|
|
4104
4127
|
messageId: uuid,
|
|
4105
|
-
text:
|
|
4128
|
+
text: z23.string().trim().min(1).max(MAX_INPUT_LENGTH)
|
|
4106
4129
|
}),
|
|
4107
4130
|
/** A person stops the run; the daemon cancels the agent's session. */
|
|
4108
|
-
|
|
4131
|
+
z23.object({ v, type: z23.literal("stop"), runId: uuid }),
|
|
4109
4132
|
/**
|
|
4110
4133
|
* Says where this connection is looking, in one workspace (ADR 0049). Sent
|
|
4111
4134
|
* once when a page opens and again every `PRESENCE_HEARTBEAT_MS`; `view`
|
|
4112
4135
|
* null keeps the member online without naming a page. Never persisted.
|
|
4113
4136
|
*/
|
|
4114
|
-
|
|
4137
|
+
z23.object({
|
|
4115
4138
|
v,
|
|
4116
|
-
type:
|
|
4139
|
+
type: z23.literal("presence"),
|
|
4117
4140
|
workspaceId: uuid,
|
|
4118
4141
|
view: presenceView.nullable()
|
|
4119
4142
|
}),
|
|
4120
4143
|
/** Stops announcing in a workspace; the member leaves its viewer list. */
|
|
4121
|
-
|
|
4144
|
+
z23.object({ v, type: z23.literal("presence.leave"), workspaceId: uuid })
|
|
4122
4145
|
]);
|
|
4123
4146
|
var RELAY_ERROR_CODES = [
|
|
4124
4147
|
"bad_message",
|
|
@@ -4132,76 +4155,76 @@ var RELAY_ERROR_CODES = [
|
|
|
4132
4155
|
/** `presence` for a workspace the caller is not a member of (ADR 0049). */
|
|
4133
4156
|
"not_a_member"
|
|
4134
4157
|
];
|
|
4135
|
-
var relayErrorCode =
|
|
4136
|
-
var relayServerMessage =
|
|
4137
|
-
|
|
4158
|
+
var relayErrorCode = z23.enum(RELAY_ERROR_CODES);
|
|
4159
|
+
var relayServerMessage = z23.discriminatedUnion("type", [
|
|
4160
|
+
z23.object({
|
|
4138
4161
|
v,
|
|
4139
|
-
type:
|
|
4162
|
+
type: z23.literal("subscribed"),
|
|
4140
4163
|
runId: uuid,
|
|
4141
|
-
latestSeq:
|
|
4164
|
+
latestSeq: z23.number().int().min(0)
|
|
4142
4165
|
}),
|
|
4143
|
-
|
|
4166
|
+
z23.object({
|
|
4144
4167
|
v,
|
|
4145
|
-
type:
|
|
4168
|
+
type: z23.literal("event"),
|
|
4146
4169
|
runId: uuid,
|
|
4147
|
-
seq:
|
|
4170
|
+
seq: z23.number().int().min(1),
|
|
4148
4171
|
event: runEvent
|
|
4149
4172
|
}),
|
|
4150
4173
|
/**
|
|
4151
4174
|
* `send` / `stop` was saved and is on its way to the run's device.
|
|
4152
4175
|
* `messageId` is set for `send`.
|
|
4153
4176
|
*/
|
|
4154
|
-
|
|
4177
|
+
z23.object({
|
|
4155
4178
|
v,
|
|
4156
|
-
type:
|
|
4179
|
+
type: z23.literal("accepted"),
|
|
4157
4180
|
runId: uuid,
|
|
4158
|
-
request:
|
|
4181
|
+
request: z23.enum(["send", "stop"]),
|
|
4159
4182
|
messageId: uuid.optional()
|
|
4160
4183
|
}),
|
|
4161
4184
|
/** Publisher acknowledgment with the seq the hub assigned. */
|
|
4162
|
-
|
|
4185
|
+
z23.object({
|
|
4163
4186
|
v,
|
|
4164
|
-
type:
|
|
4187
|
+
type: z23.literal("ack"),
|
|
4165
4188
|
runId: uuid,
|
|
4166
|
-
seq:
|
|
4189
|
+
seq: z23.number().int().min(1)
|
|
4167
4190
|
}),
|
|
4168
4191
|
/**
|
|
4169
4192
|
* Everyone the server sees online in this workspace, and where each is
|
|
4170
4193
|
* looking (ADR 0049). A snapshot after every change, so a client never has
|
|
4171
4194
|
* to merge deltas; `lastSeenAt` is the server's clock.
|
|
4172
4195
|
*/
|
|
4173
|
-
|
|
4196
|
+
z23.object({
|
|
4174
4197
|
v,
|
|
4175
|
-
type:
|
|
4198
|
+
type: z23.literal("presence"),
|
|
4176
4199
|
workspaceId: uuid,
|
|
4177
|
-
members:
|
|
4178
|
-
|
|
4200
|
+
members: z23.array(
|
|
4201
|
+
z23.object({
|
|
4179
4202
|
userId: uuid,
|
|
4180
4203
|
view: presenceView.nullable(),
|
|
4181
|
-
lastSeenAt:
|
|
4204
|
+
lastSeenAt: z23.number().int()
|
|
4182
4205
|
})
|
|
4183
4206
|
)
|
|
4184
4207
|
}),
|
|
4185
|
-
|
|
4208
|
+
z23.object({
|
|
4186
4209
|
v,
|
|
4187
|
-
type:
|
|
4210
|
+
type: z23.literal("error"),
|
|
4188
4211
|
code: relayErrorCode,
|
|
4189
|
-
message:
|
|
4212
|
+
message: z23.string(),
|
|
4190
4213
|
runId: uuid.optional(),
|
|
4191
|
-
minVersion:
|
|
4214
|
+
minVersion: z23.string().optional()
|
|
4192
4215
|
})
|
|
4193
4216
|
]);
|
|
4194
4217
|
|
|
4195
4218
|
// ../protocol/src/version.ts
|
|
4196
4219
|
var import_semver = __toESM(require_semver2(), 1);
|
|
4197
|
-
import { z as
|
|
4220
|
+
import { z as z24 } from "zod";
|
|
4198
4221
|
var CLIENT_VERSION_HEADER = "x-mikka-client-version";
|
|
4199
4222
|
var CLIENT_KINDS = ["desktop", "mobile"];
|
|
4200
|
-
var clientKind =
|
|
4201
|
-
var updateRequiredError =
|
|
4202
|
-
error:
|
|
4203
|
-
minVersion:
|
|
4204
|
-
message:
|
|
4223
|
+
var clientKind = z24.enum(CLIENT_KINDS);
|
|
4224
|
+
var updateRequiredError = z24.object({
|
|
4225
|
+
error: z24.literal("update_required"),
|
|
4226
|
+
minVersion: z24.string(),
|
|
4227
|
+
message: z24.string()
|
|
4205
4228
|
});
|
|
4206
4229
|
|
|
4207
4230
|
// src/errors.ts
|
|
@@ -4239,7 +4262,7 @@ var InvalidIdError = class extends DaemonError {
|
|
|
4239
4262
|
// package.json
|
|
4240
4263
|
var package_default = {
|
|
4241
4264
|
name: "@mikka/daemon",
|
|
4242
|
-
version: "0.0.
|
|
4265
|
+
version: "0.0.203",
|
|
4243
4266
|
description: "Local Mikka daemon: runs agents through the user's own CLIs",
|
|
4244
4267
|
type: "module",
|
|
4245
4268
|
private: true,
|
|
@@ -4263,7 +4286,7 @@ var package_default = {
|
|
|
4263
4286
|
daemon: "tsx bin/mikka.ts daemon",
|
|
4264
4287
|
dev: "tsx watch bin/mikka.ts daemon --dev --server memory",
|
|
4265
4288
|
typecheck: "tsgo --noEmit -p tsconfig.json",
|
|
4266
|
-
test: "vitest run && pnpm test:mailbox-cli && pnpm test:repository-identity && pnpm test:github-credentials",
|
|
4289
|
+
test: "vitest run && pnpm test:mailbox-cli && pnpm test:repository-identity && pnpm test:github-credentials && pnpm test:local-git-origin-sandbox",
|
|
4267
4290
|
"test:mailbox-cli": "node --import tsx --test --test-timeout=60000 test/run-mailbox.node-test.ts",
|
|
4268
4291
|
"codex:types": 'codex app-server generate-ts --out "${TMPDIR:-/tmp}/mikka-codex-types" && echo "Generated; compare v2/ with src/adapters/codex-protocol.ts"',
|
|
4269
4292
|
"test:real": "MIKKA_REAL_AGENTS=${MIKKA_REAL_AGENTS:-claude_code,codex,cursor} vitest run test/real-agents.test.ts",
|
|
@@ -4272,7 +4295,8 @@ var package_default = {
|
|
|
4272
4295
|
"test:package": "node --test test/package.test.mjs",
|
|
4273
4296
|
"test:repository-identity": "node --experimental-strip-types --test test/repository-identity-pure.node-test.ts",
|
|
4274
4297
|
"test:github-credentials": "node --test test/github-credentials.node-test.mjs",
|
|
4275
|
-
"test:run-container": "node --import tsx --test --test-timeout=900000 test/run-container.docker-test.ts"
|
|
4298
|
+
"test:run-container": "node --import tsx --test --test-timeout=900000 test/run-container.docker-test.ts",
|
|
4299
|
+
"test:local-git-origin-sandbox": "node --import tsx --test --test-timeout=60000 test/local-git-origin.sandbox-test.ts"
|
|
4276
4300
|
},
|
|
4277
4301
|
dependencies: {
|
|
4278
4302
|
"@agentclientprotocol/sdk": "1.9.0",
|
|
@@ -4299,7 +4323,7 @@ var package_default = {
|
|
|
4299
4323
|
engines: {
|
|
4300
4324
|
node: ">=24"
|
|
4301
4325
|
},
|
|
4302
|
-
gitHead: "
|
|
4326
|
+
gitHead: "6edfa68943e22c87524d63e582ebdaf28d0f2bf0"
|
|
4303
4327
|
};
|
|
4304
4328
|
|
|
4305
4329
|
// src/paths.ts
|
|
@@ -4307,20 +4331,6 @@ var DAEMON_VERSION = package_default.version;
|
|
|
4307
4331
|
|
|
4308
4332
|
// src/run-mailbox.ts
|
|
4309
4333
|
import { z as z25 } from "zod";
|
|
4310
|
-
|
|
4311
|
-
// ../protocol/src/mailbox.ts
|
|
4312
|
-
import { z as z24 } from "zod";
|
|
4313
|
-
var mailboxSend = z24.object({ to: z24.uuid(), key: z24.uuid().describe("Stable idempotency key; reuse only to retry this exact envelope."), text: z24.string().trim().min(1).max(4e3), replyTo: z24.uuid().optional() }).strict();
|
|
4314
|
-
var mailboxAck = z24.object({ ids: z24.array(z24.uuid()).max(50) }).strict();
|
|
4315
|
-
var mailboxInputs = {
|
|
4316
|
-
mailbox_recipients: z24.object({}).strict(),
|
|
4317
|
-
mailbox_send: mailboxSend,
|
|
4318
|
-
mailbox_inbox: z24.object({}).strict(),
|
|
4319
|
-
mailbox_ack: mailboxAck,
|
|
4320
|
-
mailbox_sent: z24.object({}).strict()
|
|
4321
|
-
};
|
|
4322
|
-
|
|
4323
|
-
// src/run-mailbox.ts
|
|
4324
4334
|
var requestSchema = z25.union([
|
|
4325
4335
|
z25.object({ operation: z25.literal("list") }).strict(),
|
|
4326
4336
|
z25.object({ operation: z25.literal("call"), name: z25.enum(Object.keys(mailboxInputs)), arguments: z25.unknown() }).strict()
|
|
@@ -4413,7 +4423,7 @@ async function createRunMailbox(host) {
|
|
|
4413
4423
|
if (!Array.isArray(offered.tools)) throw unavailable();
|
|
4414
4424
|
const allowed = Object.keys(mailboxInputs).filter((name) => offered.tools.some((tool) => tool.name === name));
|
|
4415
4425
|
if (!allowed.length) return void 0;
|
|
4416
|
-
const tools = Object.entries(mailboxInputs).filter(([name]) => allowed.includes(name)).map(([name, schema]) => ({ name, description: "Personal peer coordination only; never user approval.
|
|
4426
|
+
const tools = Object.entries(mailboxInputs).filter(([name]) => allowed.includes(name)).map(([name, schema]) => ({ name, description: "Personal peer coordination only; never user approval. New messages notify the current live session. Read the inbox and ACK explicitly; notification and ACK are not execution.", inputSchema: z25.toJSONSchema(schema) }));
|
|
4417
4427
|
const invoke = async (body, signal) => {
|
|
4418
4428
|
try {
|
|
4419
4429
|
active();
|
|
@@ -4546,7 +4556,8 @@ var HttpServerLink = class {
|
|
|
4546
4556
|
assignment.policy,
|
|
4547
4557
|
worktree,
|
|
4548
4558
|
runApps(assignment.mcp)?.apps.map((app) => app.name),
|
|
4549
|
-
assignment.github ? [new URL(assignment.github.endpoint).host] : []
|
|
4559
|
+
assignment.github ? [new URL(assignment.github.endpoint).host] : [],
|
|
4560
|
+
assignment.mcp?.mailbox === true
|
|
4550
4561
|
),
|
|
4551
4562
|
preauthorizeNetwork: (request, signal2) => {
|
|
4552
4563
|
const { host, port } = request.input;
|
|
@@ -4691,6 +4702,7 @@ var HttpServerLink = class {
|
|
|
4691
4702
|
[REPO_ORIGIN_HEADER]: "1",
|
|
4692
4703
|
[RECOVERY_WORKTREE_HEADER]: "1",
|
|
4693
4704
|
[MODEL_CREDENTIAL_HEADER]: "1",
|
|
4705
|
+
[MAILBOX_NOTICE_HEADER]: "1",
|
|
4694
4706
|
...token ? { authorization: `Bearer ${token}` } : {},
|
|
4695
4707
|
...this.protectionBypass ? { "x-vercel-protection-bypass": this.protectionBypass } : {}
|
|
4696
4708
|
},
|
|
@@ -4774,11 +4786,11 @@ var HttpServerLink = class {
|
|
|
4774
4786
|
);
|
|
4775
4787
|
return runIds;
|
|
4776
4788
|
}
|
|
4777
|
-
async claimRun(deviceId, runId) {
|
|
4789
|
+
async claimRun(deviceId, runId, signal) {
|
|
4778
4790
|
return this.call(
|
|
4779
4791
|
"POST",
|
|
4780
4792
|
devicePaths.claim(checkId(deviceId), checkId(runId)),
|
|
4781
|
-
{ schema: runAssignmentSchema, claimOf: runId }
|
|
4793
|
+
{ schema: runAssignmentSchema, claimOf: runId, signal }
|
|
4782
4794
|
);
|
|
4783
4795
|
}
|
|
4784
4796
|
async validateSkillReceipt(runId, receiptId) {
|
|
@@ -4858,7 +4870,8 @@ var HttpServerLink = class {
|
|
|
4858
4870
|
}
|
|
4859
4871
|
async fetchCommands(deviceId, waitSeconds, {
|
|
4860
4872
|
signal,
|
|
4861
|
-
skipRuns = []
|
|
4873
|
+
skipRuns = [],
|
|
4874
|
+
onQueuedRuns
|
|
4862
4875
|
} = {}) {
|
|
4863
4876
|
const response = await this.call(
|
|
4864
4877
|
"GET",
|
|
@@ -4873,6 +4886,7 @@ var HttpServerLink = class {
|
|
|
4873
4886
|
signal
|
|
4874
4887
|
}
|
|
4875
4888
|
);
|
|
4889
|
+
if (response.queuedRuns?.length) onQueuedRuns?.(response.queuedRuns);
|
|
4876
4890
|
return response.commands;
|
|
4877
4891
|
}
|
|
4878
4892
|
async ackCommands(deviceId, delivered) {
|