@intentic/sandbox-contract 1.217.0 → 1.218.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/publish-drafts.js +1 -1
- package/dist/publish-drafts.js.map +1 -1
- package/dist/schemas.d.ts +6 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +2 -1
- package/dist/schemas.js.map +1 -1
- package/dist/workspace-state.d.ts +64 -54
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +93 -64
- package/dist/workspace-state.js.map +1 -1
- package/package.json +4 -4
- package/src/contracts/extensions.contract.ts +1 -1
- package/src/contracts/settings.contract.ts +1 -1
- package/src/events.ts +2 -2
- package/src/publish-drafts.ts +1 -1
- package/src/schemas.ts +45 -39
- package/src/workspace-state.test.ts +226 -79
- package/src/workspace-state.ts +240 -68
package/src/schemas.ts
CHANGED
|
@@ -185,7 +185,7 @@ export const AgentTurnSchema = z
|
|
|
185
185
|
// first turn keeps its user-chosen title); an existing entry's title always wins.
|
|
186
186
|
title: z.string().max(80).optional(),
|
|
187
187
|
// Workspace-relative paths of files the user attached, already uploaded via /workspace/upload
|
|
188
|
-
// (the browser puts them under .intentic/artifacts/attachments/<uuid>/<name>). The daemon hands them to the
|
|
188
|
+
// (the browser puts them under .intentic/records/artifacts/attachments/<uuid>/<name>). The daemon hands them to the
|
|
189
189
|
// provider: Claude reads them from disk via its Read tool; Codex gets images as native inputs.
|
|
190
190
|
attachments: z.array(z.string().min(1)).max(20).optional(),
|
|
191
191
|
// Which provider (model + account) serves the turn; absent = claude. A sessionId only resumes on the
|
|
@@ -278,7 +278,7 @@ export const AgentTurnSchema = z
|
|
|
278
278
|
* It is the birth half of the turn's taint (guard/turn-taint.ts). The other half marks itself as the
|
|
279
279
|
* turn works — a fetched page, a foreign MCP server's answer — and together they are what the command
|
|
280
280
|
* gate reads before letting a command read credential material unasked. Distinct from `unattended`,
|
|
281
|
-
* which is about whether anyone is WATCHING: a
|
|
281
|
+
* which is about whether anyone is WATCHING: a Front Desk wake is both, an owner asking the agent to read
|
|
282
282
|
* a web page is neither, and each flag governs a different decision. */
|
|
283
283
|
outsideWake: z.string().min(1).optional(),
|
|
284
284
|
// How tool calls are gated for this turn (the SDK's permissionMode, verbatim). 'plan' runs the
|
|
@@ -289,7 +289,7 @@ export const AgentTurnSchema = z
|
|
|
289
289
|
/* Narrows the turn to these tool names (the SDK option of the same name — not to be confused with the
|
|
290
290
|
* daemon's MCP `tools`, which are servers). Absent ⇒ every tool the runtime has, which is what an
|
|
291
291
|
* owner-driven chat wants. Set by the automation dispatchers from Automation.allowedTools: a wake driven
|
|
292
|
-
* by an OUTSIDE message runs bypassPermissions like any other automation turn, so for a public
|
|
292
|
+
* by an OUTSIDE message runs bypassPermissions like any other automation turn, so for a public Front Desk
|
|
293
293
|
* this list is the actual boundary — prompt wording is advice, an empty toolbox is not. */
|
|
294
294
|
allowedTools: z.array(z.string().min(1)).optional(),
|
|
295
295
|
effort: z.string().optional(),
|
|
@@ -505,13 +505,13 @@ export type Loop = z.infer<typeof LoopSchema>;
|
|
|
505
505
|
// saved loop that cannot converge is a trap everyone who picks it afterwards pays a full run to discover.
|
|
506
506
|
export const loopCanConverge = (loop: Pick<Loop, "output" | "checks">): boolean => loop.output.kind !== "none" || loop.checks.length > 0;
|
|
507
507
|
|
|
508
|
-
/* Where a loop keeps what it must not lose between iterations: <workspace>/.intentic/artifacts/loops/<conversationId>/.
|
|
508
|
+
/* Where a loop keeps what it must not lose between iterations: <workspace>/.intentic/records/artifacts/loops/<conversationId>/.
|
|
509
509
|
*
|
|
510
510
|
* Under `.intentic` for the reason the acceptance runs are — it is outside every repo and bound back SHARED
|
|
511
511
|
* into an isolated turn's worktree, so the agent writes and the browser reads the same tree, with nothing to
|
|
512
512
|
* land and no git noise. `progress.md` is the loop's memory in `fresh` mode and its audit trail in `continue`
|
|
513
513
|
* mode; `iteration-<n>.json` is the verdict a `claim` stop reads. */
|
|
514
|
-
export const LOOP_DIR = `${STATE_DIR}/artifacts/loops`;
|
|
514
|
+
export const LOOP_DIR = `${STATE_DIR}/records/artifacts/loops`;
|
|
515
515
|
|
|
516
516
|
// Why an iteration ended, which is not the same question as how the LOOP ended. `continue` is the ordinary
|
|
517
517
|
// "not done yet"; `error` is a turn that surfaced an error frame, which does NOT end the loop by itself — a
|
|
@@ -1501,7 +1501,7 @@ export const SessionSummarySchema = z.object({
|
|
|
1501
1501
|
export type SessionSummary = z.infer<typeof SessionSummarySchema>;
|
|
1502
1502
|
export const SessionsListSchema = z.object({ sessions: z.array(SessionSummarySchema) });
|
|
1503
1503
|
|
|
1504
|
-
// ---- settings: per-sandbox agent settings (.intentic/settings.json) ----
|
|
1504
|
+
// ---- settings: per-sandbox agent settings (.intentic/config/settings.json) ----
|
|
1505
1505
|
|
|
1506
1506
|
// Which prompt the agent is, before this turn composes anything on top. Two built-in bases and an escape
|
|
1507
1507
|
// hatch: Intentic's own (the default), Claude Code's preset, or the owner's text. Declared out here rather
|
|
@@ -1625,7 +1625,7 @@ export type RuleFirings = z.infer<typeof RuleFiringsSchema>;
|
|
|
1625
1625
|
* adding it.
|
|
1626
1626
|
*
|
|
1627
1627
|
* builtin this image ships it — a baked tool's cheatsheet, or a core feature's
|
|
1628
|
-
* own the owner wrote it (.intentic/skills/), and only these are editable here
|
|
1628
|
+
* own the owner wrote it (.intentic/config/skills/), and only these are editable here
|
|
1629
1629
|
* capability something connected brought it: a CLI tool, a machine, a browser account, a VPN
|
|
1630
1630
|
* extension an installed extension ships it inside its checkout
|
|
1631
1631
|
* plugin a plugin capability cloned a repo that holds it
|
|
@@ -3168,7 +3168,7 @@ export const EnrollHostInputSchema = z.object({
|
|
|
3168
3168
|
});
|
|
3169
3169
|
export type EnrollHostInput = z.infer<typeof EnrollHostInputSchema>;
|
|
3170
3170
|
|
|
3171
|
-
// ---- capabilities: the sandbox's unified capability manifest (.intentic/capabilities.json) ----
|
|
3171
|
+
// ---- capabilities: the sandbox's unified capability manifest (.intentic/config/capabilities.json) ----
|
|
3172
3172
|
// Everything a user adds to a sandbox is a capability with an idempotent apply + a status check. The manifest is
|
|
3173
3173
|
// the source of truth for what's active; `mcp`-kind entries also feed the agent's MCP servers each turn. DevOps
|
|
3174
3174
|
// is the capability that scaffolds the intent/desired-state repos — until it's active the sandbox is empty.
|
|
@@ -3422,7 +3422,7 @@ export const DockerConfigSchema = z.object({
|
|
|
3422
3422
|
});
|
|
3423
3423
|
// A logged-in browser session the AGENT drives via Playwright MCP tools — for social platforms whose APIs can't
|
|
3424
3424
|
// cover "all the actions" (X reads are paywalled; X community-join and YouTube community-posts have no API). The
|
|
3425
|
-
// session lives in a persisted Chromium profile under .intentic/browser/<id>, established through the guided-login
|
|
3425
|
+
// session lives in a persisted Chromium profile under .intentic/local/browser/<id>, established through the guided-login
|
|
3426
3426
|
// WebSocket (/system/browser-login) or by the agent signing in itself. Chromium itself rides this kind's
|
|
3427
3427
|
// Dockerfile fragment, applied on an owner rebuild.
|
|
3428
3428
|
//
|
|
@@ -3793,12 +3793,12 @@ export type Persona = z.infer<typeof PersonaSchema>;
|
|
|
3793
3793
|
/* THE ONE CARD ID THE PRODUCT NAMES ITSELF — the read-only persona a public web chat answers through.
|
|
3794
3794
|
*
|
|
3795
3795
|
* Nothing else is stock: a fresh workspace has no personas at all, and every card on the Personas page is one
|
|
3796
|
-
* the owner wrote. This id is the exception because a
|
|
3796
|
+
* the owner wrote. This id is the exception because a Front Desk is driven by a stranger with nobody watching, so
|
|
3797
3797
|
* it is the one wake whose bounds cannot be left to the prompt's wording — the daemon writes the card the moment
|
|
3798
|
-
* a
|
|
3798
|
+
* a Front Desk is saved (personas/front-desk.ts) and the automations form fills a blank Front Desk persona with it.
|
|
3799
3799
|
*
|
|
3800
3800
|
* It lives HERE because those two are in different packages and must agree exactly. A literal in each would
|
|
3801
|
-
* drift into a
|
|
3801
|
+
* drift into a Front Desk pinned to a card nobody creates, and turnPersona answers a missing card by denying
|
|
3802
3802
|
* everything — a public chat that cannot even read, which is safe and useless.
|
|
3803
3803
|
*
|
|
3804
3804
|
* It is FRONT DESK and not "visitor": the card is who answers the people who arrive, not the person arriving. */
|
|
@@ -4211,10 +4211,10 @@ export const ExtensionSummarySchema = z.object({
|
|
|
4211
4211
|
commit: z.string(),
|
|
4212
4212
|
/* Where the code comes from — which is also what the web varies per row: `builtin` (image-baked, no git
|
|
4213
4213
|
* checkout, not removable) hides the uninstall affordance, `installed` (a git capability) shows the pinned
|
|
4214
|
-
* commit, `workspace` (a directory under .intentic/workspace-extensions/, created and edited in place —
|
|
4214
|
+
* commit, `workspace` (a directory under .intentic/config/workspace-extensions/, created and edited in place —
|
|
4215
4215
|
* typically by an agent) is "uninstalled" by deleting its directory. */
|
|
4216
4216
|
source: z.enum(["builtin", "installed", "workspace"]),
|
|
4217
|
-
// The owner's switch (.intentic/extension-enablement.json). A disabled extension is still listed — that's
|
|
4217
|
+
// The owner's switch (.intentic/config/extension-enablement.json). A disabled extension is still listed — that's
|
|
4218
4218
|
// what makes it switchable back on — but the daemon wires none of its contributions up and the web host
|
|
4219
4219
|
// doesn't activate it.
|
|
4220
4220
|
enabled: z.boolean(),
|
|
@@ -4268,7 +4268,7 @@ export const ExtensionsListSchema = z.object({
|
|
|
4268
4268
|
// what lets the tab say "checked an hour ago" instead of presenting staleness as certainty.
|
|
4269
4269
|
updatesCheckedAt: z.string().optional(),
|
|
4270
4270
|
});
|
|
4271
|
-
// The extension's contributes.settings values, persisted daemon-side (.intentic/extension-settings.json) keyed
|
|
4271
|
+
// The extension's contributes.settings values, persisted daemon-side (.intentic/config/extension-settings.json) keyed
|
|
4272
4272
|
// by the manifest-derived extension id — the checkout stays pristine, so a re-clone update never loses them.
|
|
4273
4273
|
// Secret-marked values are stripped from `settings`; `secretsSet` lists the secret keys that DO hold a value,
|
|
4274
4274
|
// so the UI renders "•••• (set)" without ever receiving the secret back.
|
|
@@ -4310,7 +4310,7 @@ export const ExtensionProcessStatusSchema = z.object({
|
|
|
4310
4310
|
});
|
|
4311
4311
|
export type ExtensionProcessStatus = z.infer<typeof ExtensionProcessStatusSchema>;
|
|
4312
4312
|
|
|
4313
|
-
// ---- automations: scheduled agent wake-ups (.intentic/automations.json) ----
|
|
4313
|
+
// ---- automations: scheduled agent wake-ups (.intentic/config/automations.json) ----
|
|
4314
4314
|
// An automation wakes the agent autonomously: the daemon's scheduler fires each enabled automation on its
|
|
4315
4315
|
// trigger, runs the optional guard command (a shell command in the workspace; non-zero exit skips the wake),
|
|
4316
4316
|
// then runs one agent turn with the prompt. The manifest is user config; run history is daemon-recorded.
|
|
@@ -4412,7 +4412,7 @@ export const TriggerSchema = z.discriminatedUnion("kind", [
|
|
|
4412
4412
|
]);
|
|
4413
4413
|
export type Trigger = z.infer<typeof TriggerSchema>;
|
|
4414
4414
|
|
|
4415
|
-
/* The
|
|
4415
|
+
/* The Front Desk widget's settings — everything about the embeddable chat that isn't the automation's prompt.
|
|
4416
4416
|
* Present only on `webchat` listener automations; the trigger keeps `allowedOrigins` because that one is the
|
|
4417
4417
|
* admission gate the message route reads, not a rendering choice.
|
|
4418
4418
|
*
|
|
@@ -4422,7 +4422,7 @@ export type Trigger = z.infer<typeof TriggerSchema>;
|
|
|
4422
4422
|
* the second: a field added here is invisible to the widget until it is listed there. */
|
|
4423
4423
|
export const WebchatConfigSchema = z.object({
|
|
4424
4424
|
// `public` admits anyone; `google` refuses a message that carries no verifiable Google ID token. Absent ⇒
|
|
4425
|
-
// public — a
|
|
4425
|
+
// public — a Front Desk with no access setting is the anonymous support box it looks like.
|
|
4426
4426
|
access: z.enum(["public", "google"]).optional(),
|
|
4427
4427
|
// Ask an anonymous visitor for a display name before the first message. Cosmetic: the name is typed, so it
|
|
4428
4428
|
// reaches the model as untrusted `displayName`, never as identity.
|
|
@@ -4456,7 +4456,7 @@ export const WebchatConfigSchema = z.object({
|
|
|
4456
4456
|
*
|
|
4457
4457
|
* `dailyMessageMax` absent ⇒ WEBCHAT_DAILY_MAX_DEFAULT, not uncapped. Every message here is an agent turn
|
|
4458
4458
|
* billed to the owner, and the per-minute window bounds the RATE without bounding the DAY — twenty a minute,
|
|
4459
|
-
* sustained, is tens of thousands of turns before anyone notices. A
|
|
4459
|
+
* sustained, is tens of thousands of turns before anyone notices. A Front Desk nobody configured should not be
|
|
4460
4460
|
* able to spend that, so the safe number is the one you get for free and the owner raises it deliberately.
|
|
4461
4461
|
* `conversationMessageMax` stays optional-means-uncapped: it is per visitor thread, which the daily ceiling
|
|
4462
4462
|
* already bounds in aggregate. */
|
|
@@ -4469,18 +4469,18 @@ export const WebchatConfigSchema = z.object({
|
|
|
4469
4469
|
});
|
|
4470
4470
|
export type WebchatConfig = z.infer<typeof WebchatConfigSchema>;
|
|
4471
4471
|
|
|
4472
|
-
/* The daily agent-turn ceiling a
|
|
4472
|
+
/* The daily agent-turn ceiling a Front Desk gets when its owner sets none. Lives here rather than beside the
|
|
4473
4473
|
* route that enforces it because both ends need the number: the daemon to apply it, and the automation editor
|
|
4474
4474
|
* to show the owner what they are already protected by (an invisible limit is one people hit and file as a bug).
|
|
4475
4475
|
*
|
|
4476
|
-
* 200 is chosen to be irrelevant to real support traffic and decisive against a script. A
|
|
4476
|
+
* 200 is chosen to be irrelevant to real support traffic and decisive against a script. A Front Desk answering
|
|
4477
4477
|
* two hundred questions in one UTC day is a busy one; a scripted flood reaches that in ten seconds and then
|
|
4478
4478
|
* stops costing anything. */
|
|
4479
4479
|
export const WEBCHAT_DAILY_MAX_DEFAULT = 200;
|
|
4480
4480
|
|
|
4481
4481
|
/* ---- the widget wire: three shapes GET /webchat/<id>/config, GET …/challenge and POST …/message speak ----
|
|
4482
4482
|
*
|
|
4483
|
-
* They live here, beside the stored config they derive from, because the
|
|
4483
|
+
* They live here, beside the stored config they derive from, because the Front Desk widget is a SECOND client of
|
|
4484
4484
|
* this daemon — a bundle running on a stranger's page — and the reason this package exists is that both ends of
|
|
4485
4485
|
* a wire read one definition. The widget imports these as types only (`import type`), so zod never reaches a
|
|
4486
4486
|
* visitor's browser. */
|
|
@@ -4538,13 +4538,13 @@ export const AutomationSchema = z.object({
|
|
|
4538
4538
|
// Shell command run in the workspace root before waking; exit 0 ⇒ wake, non-zero ⇒ the run is "skipped".
|
|
4539
4539
|
guard: z.string().min(1).optional(),
|
|
4540
4540
|
prompt: z.string().min(1),
|
|
4541
|
-
// The
|
|
4541
|
+
// The Front Desk widget's settings — `webchat` listener automations only, ignored on every other trigger.
|
|
4542
4542
|
webchat: WebchatConfigSchema.optional(),
|
|
4543
4543
|
/* NARROW THIS ONE JOB FURTHER than the persona it runs as — raw tool names, and the escape hatch under the
|
|
4544
4544
|
* shelves rather than the way anyone is expected to answer this question.
|
|
4545
4545
|
*
|
|
4546
4546
|
* The persona (`actsAs` below) is where a session's toolbox is decided now, because the answer is worth
|
|
4547
|
-
* reusing: the same bounds apply to the chat, the workflow and the
|
|
4547
|
+
* reusing: the same bounds apply to the chat, the workflow and the Front Desk that name the same card. This
|
|
4548
4548
|
* stays for the job that needs LESS than its persona allows — and only less, which is a rule the composer
|
|
4549
4549
|
* enforces rather than a convention: an edit here can never hand back a shelf the persona switched off. */
|
|
4550
4550
|
allowedTools: z.array(z.string().min(1)).optional(),
|
|
@@ -4557,14 +4557,14 @@ export const AutomationSchema = z.object({
|
|
|
4557
4557
|
* A sandbox holds several accounts side by side, and when the first one is out of headroom — or belongs to
|
|
4558
4558
|
* an organization that has disabled the plan — every fire of every automation errors against it until a
|
|
4559
4559
|
* human happens to read the row. Pinning the wake to an account that can actually run is the difference
|
|
4560
|
-
* between "my nightly sweep is quiet" and a
|
|
4560
|
+
* between "my nightly sweep is quiet" and a Front Desk that turns visitors away all day. */
|
|
4561
4561
|
account: z.string().optional(),
|
|
4562
4562
|
/* WHICH FACE THE WAKE SHOWS THE OUTSIDE WORLD (AgentTurnSchema.actsAs — read its note for why this is not
|
|
4563
4563
|
* spelled `account`, which is the field directly above and means who PAYS).
|
|
4564
4564
|
*
|
|
4565
4565
|
* Absent ⇒ the wake reaches NO logged-in account at all. That is the one place this whole layer stops being
|
|
4566
4566
|
* a convenience and becomes a boundary, and it is deliberately the strictest default in the schema: an
|
|
4567
|
-
* automation fires with nobody at the composer, on a prompt that — for a
|
|
4567
|
+
* automation fires with nobody at the composer, on a prompt that — for a Front Desk — a stranger helped write.
|
|
4568
4568
|
* `allowedTools` above already carries this exact reasoning for tools; an unrepeatable public post deserves
|
|
4569
4569
|
* it at least as much. An automation that genuinely means "post as us" says so, once, in a field a reviewer
|
|
4570
4570
|
* can see. */
|
|
@@ -4590,7 +4590,7 @@ export const AutomationSchema = z.object({
|
|
|
4590
4590
|
});
|
|
4591
4591
|
export type Automation = z.infer<typeof AutomationSchema>;
|
|
4592
4592
|
|
|
4593
|
-
// A wake held for owner approval (.intentic/approvals/<id>.json, one file per held wake). It snapshots the
|
|
4593
|
+
// A wake held for owner approval (.intentic/records/approvals/<id>.json, one file per held wake). It snapshots the
|
|
4594
4594
|
// trigger payload so an approved run replays exactly what fired, even across a daemon restart. The id is minted
|
|
4595
4595
|
// by the daemon (an entryId-safe filename).
|
|
4596
4596
|
export const AutomationApprovalSchema = z.object({
|
|
@@ -4606,7 +4606,7 @@ export const AutomationApprovalSchema = z.object({
|
|
|
4606
4606
|
* already opened for it and the provider session that conversation last ran on.
|
|
4607
4607
|
*
|
|
4608
4608
|
* Snapshotted for the same reason the payload is, and it is the half that was missing: without it an
|
|
4609
|
-
* approved wake fell through to minting a fresh conversation, so a
|
|
4609
|
+
* approved wake fell through to minting a fresh conversation, so a Front Desk visitor's chat became one card
|
|
4610
4610
|
* per approved message instead of the single thread the dispatcher had opened for them — a second worktree
|
|
4611
4611
|
* each time, and an agent that met the visitor again on every turn. Absent for a schedule or a webhook,
|
|
4612
4612
|
* which own no thread. */
|
|
@@ -4718,7 +4718,7 @@ export type TriggerSource = z.infer<typeof TriggerSourceSchema>;
|
|
|
4718
4718
|
* create — a shelf card on the page that makes the automation in one click, switched off, ready to read.
|
|
4719
4719
|
* The chores are all of these: upkeep nobody opens an automations page hunting for.
|
|
4720
4720
|
* configure — a shelf card that opens the dialog PREFILLED, for a template that cannot work unconfigured (a
|
|
4721
|
-
*
|
|
4721
|
+
* Front Desk with no allowed sites admits nobody, and a row that silently does nothing is worse
|
|
4722
4722
|
* than a form). */
|
|
4723
4723
|
export const TemplateOfferSchema = z.enum(["create", "configure"]);
|
|
4724
4724
|
|
|
@@ -4889,14 +4889,14 @@ export const WorkflowGateSchema = z.object({
|
|
|
4889
4889
|
/* Runs per UTC day, across every caller. A gate is a paid endpoint reachable with no person in the loop:
|
|
4890
4890
|
* one of these wired into a push-triggered pipeline is a fan-out of sessions per commit, and the
|
|
4891
4891
|
* per-request deadline bounds one call's WALL CLOCK without bounding the day's SPEND. Absent ⇒
|
|
4892
|
-
* GATE_DAILY_MAX_DEFAULT, not uncapped, for the reason the
|
|
4892
|
+
* GATE_DAILY_MAX_DEFAULT, not uncapped, for the reason the Front Desk's ceiling is not optional either.
|
|
4893
4893
|
*/
|
|
4894
4894
|
dailyMax: z.number().int().positive().optional(),
|
|
4895
4895
|
});
|
|
4896
4896
|
export type WorkflowGate = z.infer<typeof WorkflowGateSchema>;
|
|
4897
4897
|
|
|
4898
|
-
/* The gate's daily ceiling when its author sets none. Deliberately small next to the
|
|
4899
|
-
*
|
|
4898
|
+
/* The gate's daily ceiling when its author sets none. Deliberately small next to the Front Desk's 200: a
|
|
4899
|
+
* Front Desk message is one turn, a gate run is a whole graph of sessions, and the honest comparison is cost
|
|
4900
4900
|
* rather than count. Twenty is a busy day of merges and a script's first minute. */
|
|
4901
4901
|
export const GATE_DAILY_MAX_DEFAULT = 20;
|
|
4902
4902
|
|
|
@@ -5235,7 +5235,7 @@ export const PrepushRunSchema = z.object({
|
|
|
5235
5235
|
});
|
|
5236
5236
|
export type PrepushRun = z.infer<typeof PrepushRunSchema>;
|
|
5237
5237
|
|
|
5238
|
-
// ---- drafts: agent-proposed posts awaiting owner approval (.intentic/drafts/<id>.json) ----
|
|
5238
|
+
// ---- drafts: agent-proposed posts awaiting owner approval (.intentic/config/drafts/<id>.json) ----
|
|
5239
5239
|
// One JSON file per draft. The AGENT creates drafts with its normal file tools — it can't call daemon routes,
|
|
5240
5240
|
// the same split as the environment proposal — while the daemon edits/deletes them on the owner's behalf, so
|
|
5241
5241
|
// the two writers never share a file. The id IS the filename (entryId charset ⇒ path-safe); the body never
|
|
@@ -5275,7 +5275,7 @@ export const DraftSchema = z.object({
|
|
|
5275
5275
|
* address and one comment's permalink is the difference between talking to the room and answering the
|
|
5276
5276
|
* person: the publisher opens exactly this and replies where it lands. */
|
|
5277
5277
|
target: z.string().optional(),
|
|
5278
|
-
// Workspace-relative attachment paths, e.g. ".intentic/drafts/media/chart.png".
|
|
5278
|
+
// Workspace-relative attachment paths, e.g. ".intentic/config/drafts/media/chart.png".
|
|
5279
5279
|
media: z.array(z.string()).optional(),
|
|
5280
5280
|
// Suggested post time (epoch ms, the at/nextRun convention). Optional — the agent may propose without a
|
|
5281
5281
|
// date and the owner sets one at approval; an approved draft with no date posts as soon as it's picked up.
|
|
@@ -5305,7 +5305,7 @@ export type DraftSummary = z.infer<typeof DraftSummarySchema>;
|
|
|
5305
5305
|
// draft would silently never post.
|
|
5306
5306
|
export const DraftsListSchema = z.object({ drafts: z.array(DraftSummarySchema), invalid: z.array(z.string()) });
|
|
5307
5307
|
export type DraftsList = z.infer<typeof DraftsListSchema>;
|
|
5308
|
-
// entryId, not a bare string: the id becomes a filename under .intentic/drafts/.
|
|
5308
|
+
// entryId, not a bare string: the id becomes a filename under .intentic/config/drafts/.
|
|
5309
5309
|
export const DraftIdParamSchema = z.object({ id: entryId });
|
|
5310
5310
|
|
|
5311
5311
|
// ---- panels: per-repository dev servers + the content facts extensions detect on ----
|
|
@@ -5505,6 +5505,12 @@ export const MachinePairingSchema = z.object({
|
|
|
5505
5505
|
// product surfaces these, so a file edited on both ends stays stuck until someone runs the CLI.
|
|
5506
5506
|
conflicts: z.number().int().nonnegative().optional(),
|
|
5507
5507
|
paused: z.boolean().optional(),
|
|
5508
|
+
/* The SECOND session's word — the one-way mirror carrying the sandbox's state dir down (sync's backupSpec).
|
|
5509
|
+
* Reported separately rather than folded into the status above, because the two fail independently and mean
|
|
5510
|
+
* different things: the first going quiet stops the owner's edits moving, the second going quiet stops their
|
|
5511
|
+
* personas, skills, automations, drafts and transcripts from surviving the sandbox. A backup that is not
|
|
5512
|
+
* running is only dangerous while nobody knows, so it gets its own word on the line. */
|
|
5513
|
+
backupStatus: z.string().optional(),
|
|
5508
5514
|
});
|
|
5509
5515
|
export type MachinePairing = z.infer<typeof MachinePairingSchema>;
|
|
5510
5516
|
|
|
@@ -5942,9 +5948,9 @@ export const SubagentIdParamSchema = z.object({ id: z.string() });
|
|
|
5942
5948
|
|
|
5943
5949
|
// ---- environment: the overlay Dockerfile extending the sandbox image ----
|
|
5944
5950
|
// The approved file is DAEMON-COMPOSED: pinned FROM + capability fragments + the owner-approved custom section.
|
|
5945
|
-
// The agent drafts one file per thing it needs (.intentic/environment.d/<tool>.Dockerfile — custom-section
|
|
5951
|
+
// The agent drafts one file per thing it needs (.intentic/config/environment.d/<tool>.Dockerfile — custom-section
|
|
5946
5952
|
// content only, no FROM) with its normal file tools, and the daemon folds those into the single proposal file
|
|
5947
|
-
// (.intentic/environment.Dockerfile) the owner reads. The owner approves it in the browser, which stores it as
|
|
5953
|
+
// (.intentic/config/environment.Dockerfile) the owner reads. The owner approves it in the browser, which stores it as
|
|
5948
5954
|
// the custom file and recomposes the approved artifact whose sha256 the rebuild executor pins. Both composed
|
|
5949
5955
|
// files are written only when the composition CHANGES — see writeComposed, and the read loop it exists to end.
|
|
5950
5956
|
// Status is derived, never stored:
|
|
@@ -5954,7 +5960,7 @@ export const SubagentIdParamSchema = z.object({ id: z.string() });
|
|
|
5954
5960
|
const environmentFileSchema = z.object({ content: z.string(), hash: z.string() });
|
|
5955
5961
|
export const EnvironmentSchema = z.object({
|
|
5956
5962
|
proposal: environmentFileSchema.optional(),
|
|
5957
|
-
// The owner-approved agent-written custom section (.intentic/environment.custom.Dockerfile).
|
|
5963
|
+
// The owner-approved agent-written custom section (.intentic/config/environment.custom.Dockerfile).
|
|
5958
5964
|
custom: environmentFileSchema.optional(),
|
|
5959
5965
|
approved: environmentFileSchema.optional(),
|
|
5960
5966
|
// sha256 of the overlay the running container was built from (SANDBOX_ENVIRONMENT_HASH); absent = stock image.
|
|
@@ -6334,7 +6340,7 @@ export const ManifestProblemSchema = z.object({
|
|
|
6334
6340
|
});
|
|
6335
6341
|
export type ManifestProblem = z.infer<typeof ManifestProblemSchema>;
|
|
6336
6342
|
|
|
6337
|
-
// Workspace-relative path (`.intentic/settings.json`) and everything currently wrong with that file. A file
|
|
6343
|
+
// Workspace-relative path (`.intentic/config/settings.json`) and everything currently wrong with that file. A file
|
|
6338
6344
|
// with nothing wrong is absent from the list rather than present and empty.
|
|
6339
6345
|
export const ManifestProblemReportSchema = z.object({ path: z.string(), problems: z.array(ManifestProblemSchema) });
|
|
6340
6346
|
export type ManifestProblemReport = z.infer<typeof ManifestProblemReportSchema>;
|