@hachej/boring-agent 0.1.104 → 0.1.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-K25PK5EC.js → chunk-3JFPS2O6.js} +1 -0
- package/dist/{chunk-JNEKOVMJ.js → chunk-6OANSUEI.js} +1 -1
- package/dist/{chunk-4IQ4HHBG.js → chunk-7XAOVFSN.js} +7 -0
- package/dist/{chunk-I7KFNGB4.js → chunk-GS4ADE34.js} +877 -349
- package/dist/{chunk-BTYOMR7W.js → chunk-KDXIXVF6.js} +5179 -3668
- package/dist/{chunk-6DRHERVK.js → chunk-MVKXLMH3.js} +44 -2
- package/dist/chunk-YTUZFKB3.js +78 -0
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +2 -2
- package/dist/{createHarness-POZ4AXCZ.js → createHarness-AHWSC36D.js} +3 -3
- package/dist/{errors-DH7C01Pm.d.ts → errors-CEU4iujR.d.ts} +59 -4
- package/dist/{file-search-qcD5zItr.d.ts → file-search-BGUHnW9o.d.ts} +3 -3
- package/dist/front/index.d.ts +43 -7
- package/dist/front/index.js +1505 -729
- package/dist/front/styles.css +109 -15
- package/dist/{harness-Dcd08yKr.d.ts → harness-Ct0e4RWc.d.ts} +6 -3
- package/dist/{lease-DffrPrQn.d.ts → lease-nASWv2tU.d.ts} +1 -1
- package/dist/{piChatEvent-iNSXiFQq.d.ts → piChatEvent-BUWIzw5l.d.ts} +67 -36
- package/dist/{piChatSessionService-DQSQ_kWZ.d.ts → piChatSessionService-nvroRAVk.d.ts} +13 -11
- package/dist/server/agent-host/testing/gatewayConformance.d.ts +6 -5
- package/dist/server/agent-host/testing/gatewayConformance.js +57 -8
- package/dist/server/index.d.ts +207 -243
- package/dist/server/index.js +15 -9
- package/dist/server/worker/index.js +7 -7
- package/dist/shared/index.d.ts +34 -28
- package/dist/shared/index.js +8 -8
- package/dist/{types-B1xDlBSo.d.ts → types-B7-PN5jV.d.ts} +75 -23
- package/docs/AGENT_GATEWAY_V0.md +40 -2
- package/docs/ERROR_CODES.md +2 -1
- package/docs/README.md +1 -0
- package/docs/SESSION_IDENTITY.md +91 -0
- package/docs/tools.md +4 -0
- package/package.json +11 -10
- package/dist/chunk-WSQ5QNIY.js +0 -18
package/dist/shared/index.js
CHANGED
|
@@ -71,17 +71,17 @@ import {
|
|
|
71
71
|
validateConfig,
|
|
72
72
|
validateConsumptionGuards,
|
|
73
73
|
validateTool
|
|
74
|
-
} from "../chunk-
|
|
74
|
+
} from "../chunk-6OANSUEI.js";
|
|
75
75
|
import {
|
|
76
76
|
SAFE_NATIVE_SESSION_ID,
|
|
77
|
+
compareSessionOrder,
|
|
77
78
|
noopTelemetry,
|
|
78
79
|
safeCapture
|
|
79
|
-
} from "../chunk-
|
|
80
|
+
} from "../chunk-7XAOVFSN.js";
|
|
80
81
|
import {
|
|
81
82
|
AGENT_NOT_IMPLEMENTED_UNTIL_T1,
|
|
82
|
-
AgentNotImplementedError
|
|
83
|
-
|
|
84
|
-
} from "../chunk-WSQ5QNIY.js";
|
|
83
|
+
AgentNotImplementedError
|
|
84
|
+
} from "../chunk-YTUZFKB3.js";
|
|
85
85
|
import {
|
|
86
86
|
AGENT_GATEWAY_ERROR_CODES,
|
|
87
87
|
AgentGatewayError,
|
|
@@ -114,7 +114,7 @@ import {
|
|
|
114
114
|
extractToolUiMetadata,
|
|
115
115
|
isToolUiMetadata,
|
|
116
116
|
sanitizeToolUiMetadata2 as sanitizeToolUiMetadata
|
|
117
|
-
} from "../chunk-
|
|
117
|
+
} from "../chunk-MVKXLMH3.js";
|
|
118
118
|
import {
|
|
119
119
|
safeRandomUUID
|
|
120
120
|
} from "../chunk-YGRQ4Q5P.js";
|
|
@@ -127,7 +127,7 @@ import {
|
|
|
127
127
|
ERROR_CODES,
|
|
128
128
|
ErrorCode,
|
|
129
129
|
ErrorLogFieldsSchema
|
|
130
|
-
} from "../chunk-
|
|
130
|
+
} from "../chunk-3JFPS2O6.js";
|
|
131
131
|
export {
|
|
132
132
|
AGENT_GATEWAY_ERROR_CODES,
|
|
133
133
|
AGENT_KNOWLEDGE_FILESYSTEM_ID,
|
|
@@ -219,6 +219,7 @@ export {
|
|
|
219
219
|
assertNoConsumptionCycle,
|
|
220
220
|
assertValidTransition,
|
|
221
221
|
assertWithinConsumptionDepth,
|
|
222
|
+
compareSessionOrder,
|
|
222
223
|
createAgentAssetDigest,
|
|
223
224
|
createAgentDefinitionDigest,
|
|
224
225
|
createAgentDeploymentDigest,
|
|
@@ -240,7 +241,6 @@ export {
|
|
|
240
241
|
safeRandomUUID,
|
|
241
242
|
sandboxCredentialPayloadMetadataBytesV1,
|
|
242
243
|
sanitizeToolUiMetadata,
|
|
243
|
-
sessionStreamPath,
|
|
244
244
|
validateAgentDefinition,
|
|
245
245
|
validateAgentDeployment,
|
|
246
246
|
validateAgentTask,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { FastifyRequest, FastifyPluginAsync } from 'fastify';
|
|
2
|
-
import { C as ToolReadinessRequirement,
|
|
3
|
-
import { F as FileSearch, b as AgentSkillResource, c as WorkspaceAgentDirectRunInput, L as LeaseBoundWorkspaceAgent } from './file-search-
|
|
2
|
+
import { C as ToolReadinessRequirement, w as TelemetrySink, s as AgentTool, D as AgentHarnessFactory } from './harness-Ct0e4RWc.js';
|
|
3
|
+
import { F as FileSearch, b as AgentSkillResource, c as WorkspaceAgentDirectRunInput, L as LeaseBoundWorkspaceAgent } from './file-search-BGUHnW9o.js';
|
|
4
4
|
import { b as Workspace, h as RuntimeFilesystemCapability, j as WorkspaceRuntimeContext, c as Sandbox } from './sandbox-BMhut3kh.js';
|
|
5
|
-
import { b as AgentSessionRef, V as VerifiedAgentScopeClaim,
|
|
6
|
-
import { C as ChatModelSelection } from './piChatEvent-
|
|
5
|
+
import { b as AgentSessionRef, V as VerifiedAgentScopeClaim, k as AgentGatewayErrorDTO, B as JsonValue, a as AuthorizedAgentScope, A as AgentGateway, m as AgentScopeVerifier, F as ResolveAgentAccess } from './errors-CEU4iujR.js';
|
|
6
|
+
import { C as ChatModelSelection } from './piChatEvent-BUWIzw5l.js';
|
|
7
7
|
import { RuntimeHostOperations, RuntimeFilesystemBinding as RuntimeFilesystemBinding$1 } from '@hachej/boring-bash/agent';
|
|
8
|
+
import { BwrapArgsOptions } from '@hachej/boring-sandbox/providers/bwrap';
|
|
8
9
|
import { CreateNodeWorkspaceOptions, BoringAgentRuntimePaths } from '@hachej/boring-sandbox/providers/node-workspace';
|
|
9
10
|
import { PackageSource, ExtensionFactory } from '@mariozechner/pi-coding-agent';
|
|
10
11
|
|
|
@@ -86,11 +87,11 @@ interface ModelsRoutesOptions {
|
|
|
86
87
|
* (fail closed) so hosts can enforce hard stops.
|
|
87
88
|
* recordUsage once per native assistant message carrying usage.
|
|
88
89
|
* `usageId` is a stable idempotency key.
|
|
89
|
-
* settleRun when the run reaches a native terminal state and
|
|
90
|
-
*
|
|
91
|
-
* releaseRun when the run
|
|
92
|
-
*
|
|
93
|
-
*
|
|
90
|
+
* settleRun when the run reaches a native terminal state and billable
|
|
91
|
+
* usage or an authoritative all-zero usage row was recorded.
|
|
92
|
+
* releaseRun when the run does not settle: rejected execution, cleared
|
|
93
|
+
* queue, cancel/abort, error before usage, or a fail-closed
|
|
94
|
+
* fallback charge.
|
|
94
95
|
*
|
|
95
96
|
* Every run terminates with exactly one settle or release from the
|
|
96
97
|
* coordinator; sinks should still treat all four methods as idempotent
|
|
@@ -102,8 +103,8 @@ interface AgentMeteringSink {
|
|
|
102
103
|
reserveRun(input: MeteringReserveInput): Promise<MeteringReservationResult>;
|
|
103
104
|
/** Records the usage and returns the credit micros it was actually billed. The
|
|
104
105
|
* coordinator counts a usage as billable from this charged amount (not raw provider
|
|
105
|
-
* fields)
|
|
106
|
-
*
|
|
106
|
+
* fields). A complete, internally consistent all-zero report settles at zero;
|
|
107
|
+
* potentially billable usage priced to 0 retains fail-closed fallback. */
|
|
107
108
|
recordUsage(input: MeteringUsageInput): Promise<MeteringUsageResult>;
|
|
108
109
|
settleRun(input: MeteringSettleInput): Promise<void>;
|
|
109
110
|
releaseRun(input: MeteringReleaseInput): Promise<void>;
|
|
@@ -239,6 +240,12 @@ declare class ReadyStatusTracker {
|
|
|
239
240
|
* may inject an equivalent implementation with their Workspace + Sandbox pair.
|
|
240
241
|
*/
|
|
241
242
|
interface AgentRuntimeHostOperations extends RuntimeHostOperations {
|
|
243
|
+
/**
|
|
244
|
+
* Agent legally depends on the provider package, so the injected builder is
|
|
245
|
+
* typed with the canonical options here rather than the narrowed slice
|
|
246
|
+
* boring-bash declares.
|
|
247
|
+
*/
|
|
248
|
+
buildBwrapArgs(workspaceRoot: string, options?: BwrapArgsOptions): string[];
|
|
242
249
|
createNodeWorkspace(root: string, options?: CreateNodeWorkspaceOptions): Workspace;
|
|
243
250
|
getNodeWorkspaceHostRoot(workspace: Workspace): string | undefined;
|
|
244
251
|
getBoringAgentRuntimePaths(workspaceRoot: string): BoringAgentRuntimePaths;
|
|
@@ -408,7 +415,8 @@ interface RuntimeModeAdapter {
|
|
|
408
415
|
readonly readiness?: RuntimeModeReadinessHooks;
|
|
409
416
|
readonly cachedBindingHealthCheck?: RuntimeCachedBindingHealthCheck;
|
|
410
417
|
create(ctx: ModeContext): Promise<RuntimeBundle>;
|
|
411
|
-
|
|
418
|
+
/** Resolves the provider-owned workspace root in runtime coordinates. */
|
|
419
|
+
getRuntimeLayoutRoot(ctx: ModeContext): string;
|
|
412
420
|
evictCachedRuntime?(ctx: {
|
|
413
421
|
workspaceId: string;
|
|
414
422
|
}): void | Promise<void>;
|
|
@@ -529,15 +537,26 @@ interface RuntimeFilesystemBindingOperations {
|
|
|
529
537
|
path: string;
|
|
530
538
|
}): never;
|
|
531
539
|
}
|
|
540
|
+
interface RuntimeFilesystemCatalogPresentation {
|
|
541
|
+
readonly visible?: boolean;
|
|
542
|
+
readonly label?: string;
|
|
543
|
+
readonly rootDir?: '.' | `/${string}`;
|
|
544
|
+
}
|
|
532
545
|
interface RuntimeFilesystemBinding {
|
|
533
546
|
readonly filesystem: string;
|
|
534
547
|
readonly access: 'readonly' | 'readwrite';
|
|
535
548
|
readonly operations: RuntimeFilesystemBindingOperations;
|
|
549
|
+
/** User-facing catalog projection; internal routing continues to use filesystem. */
|
|
550
|
+
readonly catalog?: RuntimeFilesystemCatalogPresentation;
|
|
551
|
+
/** When present, only these addressed Agents receive this user-visible binding. */
|
|
552
|
+
readonly agentTypeIds?: readonly string[];
|
|
536
553
|
}
|
|
537
554
|
interface RuntimeBundle {
|
|
538
555
|
runtimeContext?: WorkspaceRuntimeContext;
|
|
539
556
|
/**
|
|
540
|
-
* Server-private host/storage root for host-side filesystem work.
|
|
557
|
+
* Server-private host/storage root for host-side filesystem work. Required
|
|
558
|
+
* when runtime-coordinate workspace resources have an explicit host mirror;
|
|
559
|
+
* absence means composition must not infer or project a host path. Do not use
|
|
541
560
|
* this as the agent-visible cwd; Workspace.root remains the public runtime
|
|
542
561
|
* namespace shown to tools/model.
|
|
543
562
|
*/
|
|
@@ -613,6 +632,11 @@ interface PiHarnessOptions {
|
|
|
613
632
|
/** Reject an explicit unavailable/unknown model instead of silently falling back. */
|
|
614
633
|
strictModelResolution?: boolean;
|
|
615
634
|
}
|
|
635
|
+
/** Pi harness options with the discovery flags resolved to definite booleans. */
|
|
636
|
+
type ResolvedPiHarnessOptions = PiHarnessOptions & {
|
|
637
|
+
noContextFiles: boolean;
|
|
638
|
+
noSkills: boolean;
|
|
639
|
+
};
|
|
616
640
|
interface HotReloadablePiResources {
|
|
617
641
|
additionalSkillPaths?: string[];
|
|
618
642
|
packages?: PiPackageSource[];
|
|
@@ -648,7 +672,7 @@ interface AgentSkillResourceSnapshot {
|
|
|
648
672
|
locateSkill(filePath: string): AgentSkillResource | undefined;
|
|
649
673
|
}
|
|
650
674
|
|
|
651
|
-
type AgentGatewayEffect = 'session.create' | 'session.rename' | 'session.delete' | 'session.prompt' | 'session.followup' | 'session.interrupt' | 'session.stop' | 'session.queue.clear' | 'agent.reload' | 'session.command.execute';
|
|
675
|
+
type AgentGatewayEffect = 'session.create' | 'session.rename' | 'session.archive' | 'session.delete' | 'session.prompt' | 'session.followup' | 'session.interrupt' | 'session.stop' | 'session.queue.clear' | 'agent.reload' | 'session.command.execute';
|
|
652
676
|
type AgentRequestTarget = {
|
|
653
677
|
readonly kind: 'agent';
|
|
654
678
|
readonly agentTypeId: string;
|
|
@@ -754,7 +778,23 @@ interface AgentInstructionFileRef {
|
|
|
754
778
|
readonly path: string;
|
|
755
779
|
readonly role: 'persona';
|
|
756
780
|
}
|
|
757
|
-
|
|
781
|
+
/**
|
|
782
|
+
* An authored instruction file as the fleet composer knows it: a canonical
|
|
783
|
+
* HOST absolute path, not yet addressed against any workspace.
|
|
784
|
+
*
|
|
785
|
+
* The two shapes are deliberately distinct. A multi-workspace host (the CLI
|
|
786
|
+
* hub, core) serves a DIFFERENT root per request, so composition cannot know
|
|
787
|
+
* which root a ref should be relative to; only the request can. The spec
|
|
788
|
+
* therefore carries sources, and `describe` publishes the subset that is
|
|
789
|
+
* reachable through the root actually being served (gh-1189).
|
|
790
|
+
*/
|
|
791
|
+
interface AgentInstructionSource {
|
|
792
|
+
/** Canonical absolute path on the host filesystem. */
|
|
793
|
+
readonly absolutePath: string;
|
|
794
|
+
readonly role: 'persona';
|
|
795
|
+
}
|
|
796
|
+
declare const DEFAULT_AGENT_TYPE_ID = "default";
|
|
797
|
+
interface AgentHostAgentSpec {
|
|
758
798
|
readonly agentTypeId: string;
|
|
759
799
|
readonly definition: {
|
|
760
800
|
readonly instructions: string;
|
|
@@ -775,8 +815,12 @@ interface ConfiguredAgentHostAgentSpec {
|
|
|
775
815
|
/** Host path of the package's `knowledge/` folder. */
|
|
776
816
|
readonly rootDir: string;
|
|
777
817
|
};
|
|
778
|
-
/**
|
|
779
|
-
|
|
818
|
+
/**
|
|
819
|
+
* Authored instruction sources behind `definition.instructions`, as host
|
|
820
|
+
* absolute paths. Addressed against a served workspace root per request by
|
|
821
|
+
* `describe`, never at composition time.
|
|
822
|
+
*/
|
|
823
|
+
readonly instructionSources?: readonly AgentInstructionSource[];
|
|
780
824
|
readonly plugins?: readonly {
|
|
781
825
|
/** Canonical app-preflighted plugin ID. */
|
|
782
826
|
readonly name: string;
|
|
@@ -787,12 +831,12 @@ interface ConfiguredAgentHostAgentSpec {
|
|
|
787
831
|
/** RESERVED / NOT ENFORCED. Per-turn token-limit enforcement is future work. */
|
|
788
832
|
readonly maxTokensPerTurn?: number;
|
|
789
833
|
};
|
|
834
|
+
/** Trusted host-owned provisioning grants; absent means no inherited resources. */
|
|
835
|
+
readonly provisioning?: {
|
|
836
|
+
readonly inheritSkillPaths?: boolean;
|
|
837
|
+
};
|
|
790
838
|
}
|
|
791
|
-
|
|
792
|
-
readonly agentTypeId: 'default';
|
|
793
|
-
readonly legacyDefault: true;
|
|
794
|
-
}
|
|
795
|
-
type AgentHostAgentSpec = ConfiguredAgentHostAgentSpec | LegacyDefaultAgentHostSpec;
|
|
839
|
+
type ConfiguredAgentHostAgentSpec = AgentHostAgentSpec;
|
|
796
840
|
/**
|
|
797
841
|
* Server-only compiler output. App-specific validated handles may be attached,
|
|
798
842
|
* but the Host revalidates the complete agent ID set before freezing it.
|
|
@@ -837,6 +881,12 @@ interface ResolvedAgentRuntimeScope {
|
|
|
837
881
|
readonly sessionNamespace: string;
|
|
838
882
|
readonly pi?: PiHarnessOptions;
|
|
839
883
|
readonly extraTools?: readonly AgentTool[];
|
|
884
|
+
/** Joined trusted-plugin cleanup invoked after backend session deletion succeeds. */
|
|
885
|
+
readonly onSessionDelete?: (input: {
|
|
886
|
+
readonly workspaceScopeId: string;
|
|
887
|
+
readonly agentTypeId: string;
|
|
888
|
+
readonly sessionId: string;
|
|
889
|
+
}) => Promise<void>;
|
|
840
890
|
readonly includeFilesystemTools?: boolean;
|
|
841
891
|
readonly includeUploadTools?: boolean;
|
|
842
892
|
readonly sessionDir?: string;
|
|
@@ -944,6 +994,8 @@ interface CreateAgentHostOptions {
|
|
|
944
994
|
readonly fleetCompiler: AgentFleetCompiler;
|
|
945
995
|
readonly hostId?: string;
|
|
946
996
|
readonly scopeVerifier: AgentScopeVerifier;
|
|
997
|
+
/** Optional product-owned Seat/entitlement policy; omission preserves legacy fleet-wide access. */
|
|
998
|
+
readonly resolveAgentAccess?: ResolveAgentAccess;
|
|
947
999
|
readonly runtimeModeAdapter: RuntimeModeAdapter;
|
|
948
1000
|
readonly runtimeHost?: AgentRuntimeHostOperations;
|
|
949
1001
|
readonly sessionRoot?: string;
|
|
@@ -986,4 +1038,4 @@ interface CreatedAgentHost {
|
|
|
986
1038
|
runWithWorkspaceAgent(input: AgentHostDispatcherRunInput, run: (binding: LeaseBoundWorkspaceAgent) => Promise<void>): Promise<void>;
|
|
987
1039
|
}
|
|
988
1040
|
|
|
989
|
-
export { type
|
|
1041
|
+
export { type MeteringUsageInput as $, type AgentGatewayEffect as A, type BuiltinRuntimeModeId as B, type ConfiguredAgentHostAgentSpec as C, type AgentRequestLedgerRecord as D, type AgentFleetCompiler as E, type AgentRequestTarget as F, type RuntimeFilesystemAccessDecision as G, type AgentHostDescription as H, type AgentHostDirectProjectionOptions as I, type AgentHostDispatcherRunInput as J, type AgentHostEnvironmentLease as K, type AgentHostHandle as L, type ModeContext as M, DEFAULT_AGENT_TYPE_ID as N, type MeteringErrorLogger as O, type ProvisionWorkspaceRuntimeOptions as P, type MeteringReleaseInput as Q, type RuntimeModeAdapter as R, type MeteringReleaseReason as S, type MeteringReservationResult as T, type MeteringReserveInput as U, type MeteringRunKind as V, type WorkspaceProvisioningResult as W, type MeteringRunScope as X, type MeteringRunStatus as Y, type MeteringSettleInput as Z, type MeteringUsage as _, type PiPackageSource as a, PI_PACKAGE_RESOURCE_FILTERS as a0, type PiExtensionFactory as a1, type PluginSkillSource as a2, type ResolvedEnvironmentScope as a3, type RuntimeFilesystemBindingOperations as a4, type RuntimeNodePackageSpec as a5, type RuntimeProvisioningContribution as a6, type RuntimePythonSpec as a7, type RuntimeTemplateContribution as a8, type WorkspaceProvisioningExecResult as a9, compactPiPackages as aa, mergePiPackageSources as ab, normalizeMeteringUsage as ac, piPackageSourceKey as ad, type RuntimeModeId as b, type AgentRuntimeHostOperations as c, type RuntimeBashStrategy as d, type RuntimeFilesystemStrategy as e, type WorkspaceProvisioningAdapter as f, type AgentInstructionSource as g, type AgentInstructionFileRef as h, type AgentHostAgentSpec as i, type RuntimeBundle as j, type PiHarnessOptions as k, type AgentMeteringSink as l, type RuntimeFilesystemBinding as m, type CreatedAgentHost as n, type ResolvedPiHarnessOptions as o, ReadyStatusTracker as p, type CreateAgentHostOptions as q, type CompiledAgentHostAgentSpec as r, type AgentRequestLedger as s, type AgentEffectAdmission as t, type AuthorizedEnvironmentIntent as u, type AgentHostEnvironmentScope as v, type ResolvedAgentRuntimeScope as w, type AgentRequestKey as x, type AgentRequestLedgerPrepareResult as y, type AgentRequestFailure as z };
|
package/docs/AGENT_GATEWAY_V0.md
CHANGED
|
@@ -33,16 +33,18 @@ Only the app-owned verifier returns identity facts, as
|
|
|
33
33
|
`VerifiedAgentScopeClaim`. `AgentSessionRef` deliberately carries **no
|
|
34
34
|
`hostId`** — session refs are `{ agentTypeId, sessionId }` and nothing else.
|
|
35
35
|
|
|
36
|
-
## The
|
|
36
|
+
## The 8 methods (+ close, plus optional authorization hook)
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
interface AgentGateway {
|
|
40
|
+
authorizeAgentAccess?(input: { scope; agentTypeId; operation }): Promise<void>
|
|
40
41
|
listAgents(input: ListAgentsInput): Promise<readonly AgentSummary[]>
|
|
41
42
|
listSessions(input: AuthorizedAgentSessionQuery): Promise<AgentSessionPage>
|
|
42
43
|
createSession(input: CreateAgentSessionInput): Promise<AgentSessionRef>
|
|
43
44
|
connectSession(input: ConnectAgentSessionInput): Promise<AgentSessionConnection>
|
|
44
45
|
readSessionState(input: ReadAgentSessionStateInput): Promise<AgentSessionStateSnapshot>
|
|
45
46
|
renameSession(input: RenameAgentSessionInput): Promise<AgentSessionSummary>
|
|
47
|
+
setSessionArchived(input: SetAgentSessionArchivedInput): Promise<AgentSessionSummary>
|
|
46
48
|
deleteSession(input: DeleteAgentSessionInput): Promise<void>
|
|
47
49
|
close(): Promise<void>
|
|
48
50
|
}
|
|
@@ -61,6 +63,7 @@ interface CreateAgentSessionInput { scope; agentTypeId; requestId; title? }
|
|
|
61
63
|
interface ConnectAgentSessionInput { scope; ref; cursor? }
|
|
62
64
|
interface ReadAgentSessionStateInput { scope; ref }
|
|
63
65
|
interface RenameAgentSessionInput { scope; ref; requestId; title }
|
|
66
|
+
interface SetAgentSessionArchivedInput { scope; ref; requestId; archived }
|
|
64
67
|
interface DeleteAgentSessionInput { scope; ref; requestId }
|
|
65
68
|
```
|
|
66
69
|
|
|
@@ -97,10 +100,12 @@ shorthand. Prompts add `displayContent?`, `model?`, `thinkingLevel?`,
|
|
|
97
100
|
|
|
98
101
|
## Error codes
|
|
99
102
|
|
|
100
|
-
|
|
103
|
+
Seventeen, exhaustive, order-stable, exported as both a const map and
|
|
101
104
|
`AGENT_GATEWAY_ERROR_CODES`:
|
|
102
105
|
|
|
103
106
|
`AGENT_TYPE_UNKNOWN` · `AGENT_SESSION_NOT_FOUND` · `AGENT_SCOPE_DENIED` ·
|
|
107
|
+
`AGENT_ENTITLEMENT_REQUIRED` · `AGENT_ACCESS_FORBIDDEN` ·
|
|
108
|
+
`AGENT_ACCESS_POLICY_UNAVAILABLE` ·
|
|
104
109
|
`AGENT_SESSION_REPLAY_GAP` · `AGENT_SESSION_CURSOR_AHEAD` ·
|
|
105
110
|
`AGENT_SESSION_CURSOR_EXPIRED` · `AGENT_SESSION_CURSOR_INVALID` ·
|
|
106
111
|
`AGENT_REQUEST_CONFLICT` · `AGENT_REQUEST_IN_PROGRESS` ·
|
|
@@ -152,3 +157,36 @@ rejected. Future internal/external host tiers belong to #905, not here.
|
|
|
152
157
|
|
|
153
158
|
`scripts/check-alignment-invariants.mjs` enforces that nothing outside an
|
|
154
159
|
allowlist calls it.
|
|
160
|
+
|
|
161
|
+
## Private backend seam
|
|
162
|
+
|
|
163
|
+
The session-runtime path below `EmbeddedAgentGateway` is the server-only
|
|
164
|
+
`AgentHarnessBackend`. It is private to the `createAgentHost()` construction
|
|
165
|
+
funnel: consumers still inject only `harnessFactory`, and there is no public
|
|
166
|
+
backend factory or second session path.
|
|
167
|
+
|
|
168
|
+
`AgentPromptPayload` is exposed from the shared chat barrel as a type only. Its
|
|
169
|
+
“server-only” contract means browser schemas never accept the `requireIdle`
|
|
170
|
+
selector.
|
|
171
|
+
|
|
172
|
+
`PiSessionHarnessBackend` is the sole production implementation today. It
|
|
173
|
+
adapts the unchanged `HarnessPiChatService` and owns the mapping from the
|
|
174
|
+
workspace-scoped backend address and attribution context into the legacy Pi
|
|
175
|
+
request context. The backend carries no credentials, membership authority, or
|
|
176
|
+
model catalog. Reload and slash-command host effects continue to use the
|
|
177
|
+
composition harness directly; they are host capabilities, not session-runtime
|
|
178
|
+
operations.
|
|
179
|
+
|
|
180
|
+
The Gateway request ledger is the only idempotency authority. A backend method
|
|
181
|
+
may be invoked again after a crash only through a ledger-admitted request; the
|
|
182
|
+
backend itself promises no deduplication. P1-B substitutes the adapter-private
|
|
183
|
+
replay source below `HarnessPiChatService`, not this interface. Later operations
|
|
184
|
+
may extend the interface only in their named slices (`resumePausedToolCall` in
|
|
185
|
+
A3b and `markTurnInterrupted` in A4); neither is part of the current seam.
|
|
186
|
+
|
|
187
|
+
CI pins the boundary in three directions: Agent Host production code cannot
|
|
188
|
+
import a Pi runtime, only `harnessBackend/**` can reference the concrete Pi chat
|
|
189
|
+
service, and Workspace/Core/CLI/playground consumers cannot name the private
|
|
190
|
+
backend interface or module path. Retire the legacy `PiChatSessionService` when
|
|
191
|
+
the legacy `core/createAgent` path is removed; it is intentionally not widened
|
|
192
|
+
or migrated here.
|
package/docs/ERROR_CODES.md
CHANGED
|
@@ -45,7 +45,7 @@ All API failures must use the response envelope:
|
|
|
45
45
|
| `AGENT_FLEET_MODEL_POLICY_UNCOMPILED` | Agent fleet configuration declares a model policy that the app fleet compiler did not resolve | 500 | configure app fleet compiler | error | stable (trusted API) |
|
|
46
46
|
| `AGENT_FLEET_SEAT_PERSONA_INVALID` | `loadConfiguredAgentFleet` excluded a fleet.yaml seat because its persona package failed to materialize or compose | 500 | fix persona package/spec | error | stable (trusted API) |
|
|
47
47
|
| `AGENT_FLEET_SEAT_SKILL_DIGEST_MISMATCH` | `loadConfiguredAgentFleet` excluded a fleet.yaml seat because a pinned skill's canonical content was unavailable or its digest drifted | 500 | run `pnpm write:skill-digests` or fix the skill file | error | stable (trusted API) |
|
|
48
|
-
| `AGENT_FLEET_SEAT_INSTRUCTIONS_PATH_UNPUBLISHABLE` | `
|
|
48
|
+
| `AGENT_FLEET_SEAT_INSTRUCTIONS_PATH_UNPUBLISHABLE` | `GET /api/v1/agents/:agentTypeId/describe` withheld the link to a seat's persona `instructions.md` for THIS request. Usually because the workspace root serving the request does not contain the personas tree (the fleet is composed from a repository root while the request is served from somewhere else); also when the persona canonically resolves outside that root through a symlink, when the source no longer exists, or when the seat name is not a safe path segment. NOT an HTTP error: the describe call still returns 200 — the code is only logged as a warning while that link is omitted from the response | 200 (log-only) | expected whenever a request is served from a workspace the personas are outside of — the seat runs normally, only the Agent-details instruction link is withheld. Serve the request from a workspace that contains the personas tree to get the link. If the message names an unsafe composed path, rename the seat directory to `[A-Za-z0-9][A-Za-z0-9._-]*` | warn | stable (trusted API) |
|
|
49
49
|
| `AGENT_FLEET_CONFIG_FILE_INVALID` | `loadConfiguredAgentFleet`'s fleet.yaml could not be read, parsed, or validated (whole-fleet failure, not per-seat) | 500 | fix `.agents/factory/fleet.yaml` | error | stable (trusted API) |
|
|
50
50
|
| `AGENT_DEFINITION_ID_CONFLICT` | Multiple discovered plugin packages claim the same agent definition id, so every claimant is excluded | 500 | remove or rename conflicting definitions | error | stable (trusted API) |
|
|
51
51
|
| `AGENT_DEFINITION_UNSEATED` | A discovered agent package is not named by the fleet roster and remains inert | 200 | seat it in class-B fleet config if activation is intended | info | stable (trusted API) |
|
|
@@ -98,6 +98,7 @@ All API failures must use the response envelope:
|
|
|
98
98
|
| `ABORTED` | Request cancelled via `AbortSignal` | 499 | retry | warn | stable (public API) |
|
|
99
99
|
| `PAYMENT_REQUIRED` | Billing/metering sink rejected the run (e.g. credits exhausted) | 402 | user-fix | warn | stable (public API) |
|
|
100
100
|
| `MODEL_BUDGET_EXCEEDED` | Governance model budget for this user/model is exhausted | 402 | user-fix | warn | stable (public API) |
|
|
101
|
+
| `MODEL_CONTEXT_WINDOW_EXCEEDED` | Provider rejects a model request because its conversation context is too large | 413 | compact/retry or start a smaller chat | warn | stable (public API) |
|
|
101
102
|
| `METERING_UNSUPPORTED_COMMAND` | Slash-command execution is disabled because metering cannot yet reserve/settle that path | 409 | user-fix | warn | stable (public API) |
|
|
102
103
|
| `SESSION_NOT_FOUND` | Session id does not exist | 404 | user-fix | warn | stable (public API) |
|
|
103
104
|
| `SESSION_LOCKED` | Session currently locked by concurrent writer | 409 | retry | warn | stable (public API) |
|
package/docs/README.md
CHANGED
|
@@ -82,6 +82,7 @@ the agent ↔ workspace boundary is in
|
|
|
82
82
|
|
|
83
83
|
**Contracts & operations**
|
|
84
84
|
|
|
85
|
+
- [SESSION_IDENTITY](./SESSION_IDENTITY.md) — durable session stream key, owner attributes, and v1→v2 migration contract.
|
|
85
86
|
- [ERROR_CODES](./ERROR_CODES.md) — the stable API error-code registry.
|
|
86
87
|
- [CSP](./CSP.md) — Content-Security-Policy compatibility.
|
|
87
88
|
- [ACCESSIBILITY](./ACCESSIBILITY.md) — a11y coverage and known gaps.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Session stream identity
|
|
2
|
+
|
|
3
|
+
This contract governs durable agent event-stream addressing. The code in
|
|
4
|
+
`src/shared/events.ts` is authoritative when this document and the
|
|
5
|
+
implementation disagree.
|
|
6
|
+
|
|
7
|
+
## Durable key
|
|
8
|
+
|
|
9
|
+
A session stream is keyed by `(workspaceScopeId, sessionId)`. Its path is:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
sessions/<enc(workspaceScopeId)>/<enc(sessionId)>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`enc` percent-encodes every byte outside `[A-Za-z0-9._-]`, using uppercase
|
|
16
|
+
hex. Both fields are opaque, non-empty, well-formed Unicode strings; session
|
|
17
|
+
ids need not be UUIDs.
|
|
18
|
+
`sessionStreamPath(identity)` is the only constructor and
|
|
19
|
+
`parseSessionStreamPath(path)` accepts only the canonical encoding.
|
|
20
|
+
The value helpers are server-internal and are not exported from the package's
|
|
21
|
+
shared public barrel; only the `SessionStreamIdentity` type is public there.
|
|
22
|
+
|
|
23
|
+
The process-local Pi cache may still use a JSON tuple, but it is not a durable
|
|
24
|
+
key. Gateway host maps use `(workspaceScopeId, agentTypeId, sessionId)`, and
|
|
25
|
+
Pi transcript directories use their existing agent and workspace namespace.
|
|
26
|
+
Neither grammar may be embedded into a durable stream path.
|
|
27
|
+
|
|
28
|
+
When no event store is configured, legacy/headless callers may omit
|
|
29
|
+
`workspaceId`. The service preserves their pre-durability JSON cache key and
|
|
30
|
+
never constructs or validates a durable path. Once an event store is present,
|
|
31
|
+
both identity fields are required and invalid identity or durable-read errors
|
|
32
|
+
surface instead of being treated as a missing transcript.
|
|
33
|
+
|
|
34
|
+
## Owner attributes
|
|
35
|
+
|
|
36
|
+
`boring_event_stream_owners` stores one row for each addressed session stream:
|
|
37
|
+
|
|
38
|
+
- `path` is the primary key.
|
|
39
|
+
- `workspace_scope_id` and `session_id` repeat the durable identity and are
|
|
40
|
+
indexed together.
|
|
41
|
+
- `agent_type_id` is required for newly opened channels but is an attribute,
|
|
42
|
+
not part of the stream key.
|
|
43
|
+
- `auth_subject_id` is execution attribution, never ownership.
|
|
44
|
+
- `seat_id` and `thread_id` are reserved nullable columns; A1 defines no
|
|
45
|
+
semantics or foreign keys for them.
|
|
46
|
+
- `key_version` is `2` for streams created with this grammar and `1` for
|
|
47
|
+
migrated rows.
|
|
48
|
+
|
|
49
|
+
There is deliberately no foreign key. SQLite foreign-key enforcement is not
|
|
50
|
+
enabled on this connection; migration validation and store transactions enforce
|
|
51
|
+
the relationship instead.
|
|
52
|
+
|
|
53
|
+
`auth_subject_id` uses first-writer semantics: the first successful
|
|
54
|
+
`createSessionStream` claim records it, and later opens do not replace it.
|
|
55
|
+
This is attribution for the opening execution, not a durable authorization or
|
|
56
|
+
ownership decision.
|
|
57
|
+
|
|
58
|
+
## Schema v1 to v2
|
|
59
|
+
|
|
60
|
+
Opening a v1 database runs one `BEGIN IMMEDIATE` migration. It preflights every
|
|
61
|
+
old stream into `boring_event_stream_migration_v2` by parent `rowid`, raw
|
|
62
|
+
`path`, and `typeof(path)`, validates unique targets, every parent's path and
|
|
63
|
+
metadata, per-stream row counts and maximum sequence values, every owner row,
|
|
64
|
+
and every child row before swapping paths across all three event tables.
|
|
65
|
+
|
|
66
|
+
The collision rules are exhaustive:
|
|
67
|
+
|
|
68
|
+
1. A single old row rekeys to its v2 path.
|
|
69
|
+
2. For an empty-user row colliding with user-bearing rows, the empty-user row
|
|
70
|
+
wins and the others are quarantined.
|
|
71
|
+
3. If several user-bearing rows collide without an empty-user row, all are
|
|
72
|
+
quarantined because their sequence spaces cannot be merged safely.
|
|
73
|
+
4. Non-matching, malformed, or otherwise ambiguous old paths are quarantined.
|
|
74
|
+
|
|
75
|
+
Legacy identities containing ill-formed Unicode are quarantined with reason
|
|
76
|
+
`unencodable-identity`. Non-TEXT parent paths (including SQL `NULL`) use a
|
|
77
|
+
rowid-safe quarantine destination; their raw original value/type remains in
|
|
78
|
+
the manifest. No encoding failure aborts migration of the remaining rows.
|
|
79
|
+
|
|
80
|
+
Ordinary quarantine destinations are `quarantine/v1/<enc(oldPath)>`; rowid-safe
|
|
81
|
+
destinations cover values that cannot be encoded. Rows are never dropped. The
|
|
82
|
+
swap is validated again before `schema_version` becomes `2`.
|
|
83
|
+
Concurrent openers serialize on the immediate transaction, re-read the version
|
|
84
|
+
under the lock, and only one migrates. A migrated owner has
|
|
85
|
+
`agent_type_id = NULL` until the next legitimate channel open backfills it from
|
|
86
|
+
the composition's explicit agent type.
|
|
87
|
+
|
|
88
|
+
The migration is a rollback fence, not a reversible downgrade. Disable
|
|
89
|
+
`BORING_CHAT_DURABLE_STREAM` before running an old binary; an old binary pointed
|
|
90
|
+
at a v2 file refuses it with `EventStreamSchemaVersionError` rather than writing
|
|
91
|
+
mixed path grammars.
|
package/docs/tools.md
CHANGED
|
@@ -93,6 +93,10 @@ resources declared in `package.json#pi` (`extensions`, `skills`, `prompts`, and
|
|
|
93
93
|
place for tools/skills that should update without restarting the workspace
|
|
94
94
|
server.
|
|
95
95
|
|
|
96
|
+
## Optional trusted plugin tools
|
|
97
|
+
|
|
98
|
+
App hosts may add tools through trusted Workspace server plugins. Disposable lease support is additive: the optional sandbox plugin supplies `sandbox` and `sandbox_bash` without changing canonical bash or file-tool schemas. Agent-authored plugin selection alone cannot grant that host authority.
|
|
99
|
+
|
|
96
100
|
## Runtime modes
|
|
97
101
|
|
|
98
102
|
See [runtime.md](./runtime.md) for how tool execution is sandboxed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hachej/boring-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.107",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Pane-embeddable coding agent. Ships direct/local/vercel-sandbox execution modes behind one interface.",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"docs"
|
|
70
70
|
],
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@mariozechner/pi-coding-agent": "npm:@earendil-works/pi-coding-agent@0.
|
|
72
|
+
"@mariozechner/pi-coding-agent": "npm:@earendil-works/pi-coding-agent@0.84.3",
|
|
73
73
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
74
74
|
"@radix-ui/react-collapsible": "^1.1.20",
|
|
75
75
|
"@radix-ui/react-dialog": "^1.1.23",
|
|
@@ -85,12 +85,12 @@
|
|
|
85
85
|
"@streamdown/math": "^1.0.2",
|
|
86
86
|
"@streamdown/mermaid": "^1.0.2",
|
|
87
87
|
"@tanstack/react-query": "^5.101.4",
|
|
88
|
-
"ai": "^7.0.
|
|
88
|
+
"ai": "^7.0.68",
|
|
89
89
|
"class-variance-authority": "^0.7.1",
|
|
90
90
|
"clsx": "^2.1.1",
|
|
91
91
|
"cmdk": "^1.1.1",
|
|
92
92
|
"diff": "^9.0.0",
|
|
93
|
-
"fastify": "^5.
|
|
93
|
+
"fastify": "^5.12.1",
|
|
94
94
|
"lucide-react": "^1.31.0",
|
|
95
95
|
"motion": "^13.1.0",
|
|
96
96
|
"nanoid": "^6.0.0",
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
"use-stick-to-bottom": "^1.1.6",
|
|
101
101
|
"yaml": "^2.9.0",
|
|
102
102
|
"zod": "^3.25.76",
|
|
103
|
-
"@hachej/boring-bash": "0.1.
|
|
104
|
-
"@hachej/boring-sandbox": "0.1.
|
|
105
|
-
"@hachej/boring-ui-kit": "0.1.
|
|
103
|
+
"@hachej/boring-bash": "0.1.107",
|
|
104
|
+
"@hachej/boring-sandbox": "0.1.107",
|
|
105
|
+
"@hachej/boring-ui-kit": "0.1.107"
|
|
106
106
|
},
|
|
107
107
|
"devDependencies": {
|
|
108
108
|
"@vercel/sandbox": "3.0.0",
|
|
@@ -122,13 +122,14 @@
|
|
|
122
122
|
"tsx": "^4.23.6",
|
|
123
123
|
"typescript": "^6.0.3",
|
|
124
124
|
"vite": "^8.2.1",
|
|
125
|
-
"
|
|
125
|
+
"@earendil-works/pi-ai": "0.84.3",
|
|
126
|
+
"vitest": "^4.1.11"
|
|
126
127
|
},
|
|
127
128
|
"peerDependencies": {
|
|
128
129
|
"react": "^18.0.0 || ^19.0.0",
|
|
129
130
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
130
131
|
"tailwindcss": ">=3.4.0 || >=4.0.0",
|
|
131
|
-
"vitest": "^4.1.
|
|
132
|
+
"vitest": "^4.1.11"
|
|
132
133
|
},
|
|
133
134
|
"peerDependenciesMeta": {
|
|
134
135
|
"react": {
|
|
@@ -145,7 +146,7 @@
|
|
|
145
146
|
}
|
|
146
147
|
},
|
|
147
148
|
"scripts": {
|
|
148
|
-
"build": "tsup &&
|
|
149
|
+
"build": "tsup && pnpm run build:assert",
|
|
149
150
|
"build:dev": "{ [ -d '../ui/dist' ] || pnpm --filter @hachej/boring-ui-kit build; } && tsup --config tsup.dev.config.ts && node ./scripts/build-front-css.mjs",
|
|
150
151
|
"build:assert": "node ./scripts/assert-build-artifacts.mjs",
|
|
151
152
|
"dev": "tsx src/server/dev.ts",
|
package/dist/chunk-WSQ5QNIY.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// src/shared/events.ts
|
|
2
|
-
var AGENT_NOT_IMPLEMENTED_UNTIL_T1 = "ERR_NOT_IMPLEMENTED_UNTIL_T1";
|
|
3
|
-
function sessionStreamPath(sessionId) {
|
|
4
|
-
return `sessions/${sessionId}`;
|
|
5
|
-
}
|
|
6
|
-
var AgentNotImplementedError = class extends Error {
|
|
7
|
-
code = AGENT_NOT_IMPLEMENTED_UNTIL_T1;
|
|
8
|
-
constructor(message = "This agent capability is not implemented until T1.") {
|
|
9
|
-
super(message);
|
|
10
|
-
this.name = "AgentNotImplementedError";
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export {
|
|
15
|
-
AGENT_NOT_IMPLEMENTED_UNTIL_T1,
|
|
16
|
-
sessionStreamPath,
|
|
17
|
-
AgentNotImplementedError
|
|
18
|
-
};
|