newmark-agent 0.6.1 → 0.6.3

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.
@@ -0,0 +1,197 @@
1
+ /**
2
+ * continuation-v1 contracts.
3
+ *
4
+ * These are the runtime-checked boundaries shared by the PC GUI, the hosted
5
+ * mobile API and the isolated runtimes. A view may read a snapshot, but it can
6
+ * never supply the execution identity that a write is allowed to use.
7
+ */
8
+ export type WorkspaceId = string;
9
+ export type RootId = string;
10
+ export type BranchId = string;
11
+ export type BuildId = string;
12
+ export type AttemptId = string;
13
+ export type CommandId = string;
14
+ export type SnapshotId = string;
15
+ export declare const CONTINUATION_SCHEMA_VERSION: 1;
16
+ export type BuildStatus = 'QUEUED' | 'RUNNING' | 'WAITING_TOOL' | 'WAITING_APPROVAL' | 'WAITING_SUBAGENT' | 'FINALIZING' | 'SUCCEEDED' | 'FAILED' | 'CANCELLED';
17
+ export type AttemptStatus = 'RUNNING' | 'COMPLETED' | 'FAILED' | 'CANCELLED' | 'EXPIRED';
18
+ export type ContinuationErrorCode = 'TARGET_REQUIRED' | 'ROUTE_MISMATCH' | 'QUEUE_REVISION_CONFLICT' | 'ANCHOR_NOT_IN_LINEAGE' | 'ANCHOR_NOT_COMMITTED' | 'IDEMPOTENCY_KEY_REUSE' | 'STALE_EXECUTION' | 'FINAL_ALREADY_COMMITTED' | 'BUILD_NOT_READY' | 'BRANCH_PAUSED' | 'EFFECT_UNCERTAIN' | 'UNKNOWN_BRANCH' | 'UNKNOWN_BUILD' | 'UNKNOWN_COMMAND';
19
+ export declare class ContinuationError extends Error {
20
+ readonly code: ContinuationErrorCode;
21
+ readonly detail?: Record<string, unknown> | undefined;
22
+ constructor(code: ContinuationErrorCode, message: string, detail?: Record<string, unknown> | undefined);
23
+ }
24
+ export interface CommandTarget {
25
+ workspaceId: WorkspaceId;
26
+ expectedRootId: RootId;
27
+ branchId: BranchId;
28
+ }
29
+ export interface BuildInput {
30
+ text: string;
31
+ images?: Array<{
32
+ dataUrl: string;
33
+ name?: string;
34
+ type?: string;
35
+ }>;
36
+ attachments?: Array<{
37
+ id: string;
38
+ name: string;
39
+ mimeType: string;
40
+ dataUrl?: string;
41
+ }>;
42
+ requestedMode?: string;
43
+ goalObjective?: string;
44
+ /** Provider-qualified model frozen at command acceptance time. */
45
+ modelSelection?: string;
46
+ /** Branch node captured when the user submitted the command. */
47
+ branchNodeId?: string;
48
+ branchPath?: string[];
49
+ }
50
+ export interface EnqueueBuildCommand {
51
+ schemaVersion: typeof CONTINUATION_SCHEMA_VERSION;
52
+ type: 'ENQUEUE_BUILD';
53
+ commandId: CommandId;
54
+ actorId: string;
55
+ target: CommandTarget;
56
+ expectedTailBuildId: BuildId | null;
57
+ expectedQueueRevision: number;
58
+ input: BuildInput;
59
+ recipeSnapshotId: SnapshotId;
60
+ createdAt: string;
61
+ }
62
+ export interface CommandReceipt {
63
+ schemaVersion: typeof CONTINUATION_SCHEMA_VERSION;
64
+ commandId: CommandId;
65
+ requestHash: string;
66
+ workspaceId: WorkspaceId;
67
+ rootId: RootId;
68
+ branchId: BranchId;
69
+ buildId: BuildId;
70
+ parentBuildId: BuildId | null;
71
+ queueSequence: number;
72
+ queueRevision: number;
73
+ lifecycleRevision: number;
74
+ acceptedAt: string;
75
+ duplicate?: boolean;
76
+ }
77
+ export interface ExecutionScope {
78
+ workspaceId: WorkspaceId;
79
+ rootId: RootId;
80
+ branchId: BranchId;
81
+ buildId: BuildId;
82
+ attemptId: AttemptId;
83
+ fence: number;
84
+ parentBuildId: BuildId | null;
85
+ baseContextSnapshotId: SnapshotId;
86
+ environmentSnapshotId: SnapshotId;
87
+ workerCapability: string;
88
+ }
89
+ export interface BranchGuardSnapshot {
90
+ branchId: BranchId;
91
+ activeBuildId: BuildId | null;
92
+ activeAttemptId: AttemptId | null;
93
+ fence: number;
94
+ leaseUntil: number;
95
+ workerCapability: string;
96
+ }
97
+ export interface QueueSnapshot {
98
+ workspaceId: WorkspaceId;
99
+ rootId: RootId;
100
+ branchId: BranchId;
101
+ headBuildId: BuildId | null;
102
+ tailBuildId: BuildId | null;
103
+ queueRevision: number;
104
+ lifecycleRevision: number;
105
+ paused: boolean;
106
+ activeBuildId: BuildId | null;
107
+ guard: BranchGuardSnapshot;
108
+ builds: BuildRecord[];
109
+ }
110
+ export interface BuildRecord {
111
+ buildId: BuildId;
112
+ workspaceId: WorkspaceId;
113
+ rootId: RootId;
114
+ branchId: BranchId;
115
+ parentBuildId: BuildId | null;
116
+ inputHash: string;
117
+ input: BuildInput;
118
+ recipeSnapshotId: SnapshotId;
119
+ status: BuildStatus;
120
+ queueSequence: number;
121
+ createdAt: string;
122
+ updatedAt: string;
123
+ finalId?: string;
124
+ waitingReason?: string;
125
+ }
126
+ export interface AttemptRecord {
127
+ attemptId: AttemptId;
128
+ buildId: BuildId;
129
+ branchId: BranchId;
130
+ fence: number;
131
+ status: AttemptStatus;
132
+ leaseUntil: number;
133
+ workerCapability: string;
134
+ startedAt: string;
135
+ endedAt?: string;
136
+ }
137
+ export interface FinalRecord {
138
+ finalId: string;
139
+ buildId: BuildId;
140
+ branchId: BranchId;
141
+ finalHash: string;
142
+ stateSnapshotId: SnapshotId;
143
+ text: string;
144
+ committedAt: string;
145
+ }
146
+ export interface ContinuationEvent {
147
+ eventId: string;
148
+ cursor: number;
149
+ type: 'BuildAccepted' | 'AttemptStarted' | 'AttemptHeartbeat' | 'BuildCommitted' | 'BuildFailed' | 'BuildCancelled' | 'BranchForked' | 'BranchPaused' | 'BranchResumed' | 'StaleWriteRejected';
150
+ workspaceId: WorkspaceId;
151
+ rootId: RootId;
152
+ branchId: BranchId;
153
+ buildId: BuildId | null;
154
+ attemptId: AttemptId | null;
155
+ fence: number | null;
156
+ at: string;
157
+ payload?: Record<string, unknown>;
158
+ }
159
+ export interface LedgerFile {
160
+ version: typeof CONTINUATION_SCHEMA_VERSION;
161
+ workspaceId: WorkspaceId;
162
+ roots: Record<RootId, {
163
+ rootId: RootId;
164
+ workspaceId: WorkspaceId;
165
+ defaultBranchId: BranchId;
166
+ createdAt: string;
167
+ }>;
168
+ branches: Record<BranchId, BranchRecord>;
169
+ builds: Record<BuildId, BuildRecord>;
170
+ attempts: Record<AttemptId, AttemptRecord>;
171
+ guards: Record<BranchId, BranchGuardSnapshot>;
172
+ commands: Record<string, CommandReceipt>;
173
+ finals: Record<BuildId, FinalRecord>;
174
+ events: ContinuationEvent[];
175
+ nextEventCursor: number;
176
+ nextQueueSequence: number;
177
+ }
178
+ export interface BranchRecord {
179
+ branchId: BranchId;
180
+ workspaceId: WorkspaceId;
181
+ rootId: RootId;
182
+ parentAnchorBuildId: BuildId | null;
183
+ headBuildId: BuildId | null;
184
+ tailBuildId: BuildId | null;
185
+ queueRevision: number;
186
+ lifecycleRevision: number;
187
+ paused: boolean;
188
+ createdAt: string;
189
+ updatedAt: string;
190
+ }
191
+ export declare function stableJson(value: unknown): string;
192
+ export declare function emptyLedger(workspaceId: WorkspaceId): LedgerFile;
193
+ export declare function defaultGuard(branchId: BranchId): BranchGuardSnapshot;
194
+ export declare function commandKey(actorId: string, commandId: CommandId): string;
195
+ export declare function buildInputHash(input: BuildInput): string;
196
+ export declare function requestHash(command: EnqueueBuildCommand): string;
197
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ /**
3
+ * continuation-v1 contracts.
4
+ *
5
+ * These are the runtime-checked boundaries shared by the PC GUI, the hosted
6
+ * mobile API and the isolated runtimes. A view may read a snapshot, but it can
7
+ * never supply the execution identity that a write is allowed to use.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ContinuationError = exports.CONTINUATION_SCHEMA_VERSION = void 0;
11
+ exports.stableJson = stableJson;
12
+ exports.emptyLedger = emptyLedger;
13
+ exports.defaultGuard = defaultGuard;
14
+ exports.commandKey = commandKey;
15
+ exports.buildInputHash = buildInputHash;
16
+ exports.requestHash = requestHash;
17
+ exports.CONTINUATION_SCHEMA_VERSION = 1;
18
+ class ContinuationError extends Error {
19
+ code;
20
+ detail;
21
+ constructor(code, message, detail) {
22
+ super(message);
23
+ this.code = code;
24
+ this.detail = detail;
25
+ this.name = 'ContinuationError';
26
+ }
27
+ }
28
+ exports.ContinuationError = ContinuationError;
29
+ function stableJson(value) {
30
+ if (value === null || typeof value !== 'object')
31
+ return JSON.stringify(value);
32
+ if (Array.isArray(value))
33
+ return `[${value.map(item => stableJson(item)).join(',')}]`;
34
+ const record = value;
35
+ return `{${Object.keys(record).sort().map(key => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(',')}}`;
36
+ }
37
+ function emptyLedger(workspaceId) {
38
+ return {
39
+ version: exports.CONTINUATION_SCHEMA_VERSION,
40
+ workspaceId,
41
+ roots: {},
42
+ branches: {},
43
+ builds: {},
44
+ attempts: {},
45
+ guards: {},
46
+ commands: {},
47
+ finals: {},
48
+ events: [],
49
+ nextEventCursor: 1,
50
+ nextQueueSequence: 1,
51
+ };
52
+ }
53
+ function defaultGuard(branchId) {
54
+ return { branchId, activeBuildId: null, activeAttemptId: null, fence: 0, leaseUntil: 0, workerCapability: '' };
55
+ }
56
+ function commandKey(actorId, commandId) {
57
+ return `${actorId}\u0000${commandId}`;
58
+ }
59
+ function buildInputHash(input) {
60
+ return require('crypto').createHash('sha256').update(stableJson(input)).digest('hex').slice(0, 24);
61
+ }
62
+ function requestHash(command) {
63
+ return require('crypto').createHash('sha256').update(stableJson({
64
+ type: command.type,
65
+ target: command.target,
66
+ expectedTailBuildId: command.expectedTailBuildId,
67
+ expectedQueueRevision: command.expectedQueueRevision,
68
+ input: command.input,
69
+ recipeSnapshotId: command.recipeSnapshotId,
70
+ })).digest('hex');
71
+ }
72
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1,178 @@
1
+ import { BranchId, BranchRecord, BuildId, BuildInput, BuildRecord, CommandReceipt, ContinuationEvent, EnqueueBuildCommand, ExecutionScope, FinalRecord, QueueSnapshot, RootId, SnapshotId } from './contracts';
2
+ export interface GuardedContinuationStoreOptions {
3
+ /** Lease duration for one attempt. */
4
+ leaseMs?: number;
5
+ /** Maximum retained append-only events per workspace ledger. */
6
+ eventRetention?: number;
7
+ }
8
+ /**
9
+ * Single-writer continuation ledger for one workspace.
10
+ *
11
+ * The spec's reference uses SQLite. This implementation keeps the same
12
+ * boundaries with a lock-file + atomic-replace JSON ledger because the project
13
+ * does not ship a native SQLite module and an Electron native dependency would
14
+ * change the packaging/signing contract. All continuation writes must go
15
+ * through this class; callers never mutate the ledger directly.
16
+ */
17
+ export declare class GuardedContinuationStore {
18
+ private readonly workspacePath;
19
+ private readonly workspaceId;
20
+ private readonly ledgerPath;
21
+ private readonly lockPath;
22
+ private readonly leaseMs;
23
+ private readonly eventRetention;
24
+ private fingerprint;
25
+ private cached;
26
+ constructor(workspacePath: string, workspaceId: string, options?: GuardedContinuationStoreOptions);
27
+ get filePath(): string;
28
+ ensureRoot(rootId: RootId, defaultBranchId: BranchId): void;
29
+ ensureBranch(input: {
30
+ rootId: RootId;
31
+ branchId: BranchId;
32
+ parentAnchorBuildId: BuildId | null;
33
+ }): BranchRecord;
34
+ getReceipt(actorId: string, commandId: string): CommandReceipt | undefined;
35
+ enqueueBuild(command: EnqueueBuildCommand): CommandReceipt;
36
+ claimBuild(input: {
37
+ workspaceId: string;
38
+ rootId: RootId;
39
+ branchId: BranchId;
40
+ workerCapability: string;
41
+ now?: number;
42
+ }): ExecutionScope | null;
43
+ updateQueuedBuild(input: {
44
+ workspaceId: string;
45
+ rootId: RootId;
46
+ branchId: BranchId;
47
+ buildId: BuildId;
48
+ input: BuildInput;
49
+ }): BuildRecord;
50
+ deleteQueuedBuild(input: {
51
+ workspaceId: string;
52
+ rootId: RootId;
53
+ branchId: BranchId;
54
+ buildId: BuildId;
55
+ }): void;
56
+ reorderQueuedBuilds(input: {
57
+ workspaceId: string;
58
+ rootId: RootId;
59
+ branchId: BranchId;
60
+ orderedBuildIds: BuildId[];
61
+ }): QueueSnapshot;
62
+ heartbeat(scope: Pick<ExecutionScope, 'branchId' | 'buildId' | 'attemptId' | 'fence'>, now?: number): boolean;
63
+ commitFinal(input: {
64
+ scope: ExecutionScope;
65
+ text: string;
66
+ finalHash?: string;
67
+ stateSnapshotId?: SnapshotId;
68
+ now?: number;
69
+ }): FinalRecord;
70
+ /**
71
+ * Trusted external-owner completion.
72
+ *
73
+ * A Flow is a kernel-owned external run, not a leased model worker. It still
74
+ * has to be a durable build so queued Goal/Next successors have a committed
75
+ * parent. This path validates the parent/head relation transactionally but
76
+ * does not require a BranchGuard attempt; the kernel owns the Flow lifetime.
77
+ * If the build is not the next ready build, it stays QUEUED and the caller
78
+ * must retry after the predecessor commits.
79
+ */
80
+ commitExternalBuild(input: {
81
+ workspaceId: string;
82
+ rootId: RootId;
83
+ branchId: BranchId;
84
+ buildId: BuildId;
85
+ text?: string;
86
+ now?: number;
87
+ }): boolean;
88
+ /**
89
+ * Claim a new attempt for an existing external Flow build (suspend/resume).
90
+ * The build identity and fixed parent are preserved; only the attempt/fence
91
+ * advance. This is the external-owner equivalent of retryBuild.
92
+ */
93
+ claimExternalBuild(input: {
94
+ workspaceId: string;
95
+ rootId: RootId;
96
+ branchId: BranchId;
97
+ buildId: BuildId;
98
+ workerCapability?: string;
99
+ now?: number;
100
+ }): ExecutionScope;
101
+ failBuild(input: {
102
+ scope: ExecutionScope;
103
+ reason: string;
104
+ now?: number;
105
+ }): void;
106
+ cancelBuild(input: {
107
+ workspaceId: string;
108
+ rootId: RootId;
109
+ branchId: BranchId;
110
+ buildId: BuildId;
111
+ now?: number;
112
+ }): void;
113
+ retryBuild(input: {
114
+ workspaceId: string;
115
+ rootId: RootId;
116
+ branchId: BranchId;
117
+ buildId: BuildId;
118
+ }): BuildRecord;
119
+ /**
120
+ * Idempotent failure recovery for an input that was never accepted.
121
+ *
122
+ * Stop/archive may release the branch guard before the runtime reports the
123
+ * failure. In that case the build is still the same durable row and must be
124
+ * returned to QUEUED for an explicit resume instead of being stranded in
125
+ * RUNNING (or permanently FAILED). A committed build is never requeued.
126
+ */
127
+ requeueBuild(input: {
128
+ workspaceId: string;
129
+ rootId: RootId;
130
+ branchId: BranchId;
131
+ buildId: BuildId;
132
+ }): BuildRecord;
133
+ forkBranch(input: {
134
+ commandId: string;
135
+ actorId: string;
136
+ workspaceId: string;
137
+ sourceBranchId: BranchId;
138
+ anchorBuildId: BuildId;
139
+ newBranchId: BranchId;
140
+ }): BranchRecord;
141
+ setPaused(input: {
142
+ workspaceId: string;
143
+ rootId: RootId;
144
+ branchId: BranchId;
145
+ paused: boolean;
146
+ }): boolean;
147
+ snapshot(input: {
148
+ workspaceId: string;
149
+ rootId: RootId;
150
+ branchId: BranchId;
151
+ }): QueueSnapshot;
152
+ private snapshotUnlocked;
153
+ events(afterCursor?: number, limit?: number): ContinuationEvent[];
154
+ recoverExpiredLeases(now?: number): number;
155
+ private terminateAttempt;
156
+ private releaseExpiredGuard;
157
+ private markDependentsBlocked;
158
+ private hasCommittedDescendant;
159
+ private isAncestorOfHead;
160
+ private ensureBranchRecord;
161
+ private requireBranch;
162
+ private ensureGuard;
163
+ /**
164
+ * Release the active attempt without ever moving the branch fence backward.
165
+ * A recovered/completed attempt's fence stays as the monotonic high-water
166
+ * mark; the next claim increments it again.
167
+ */
168
+ private releaseGuard;
169
+ private appendEvent;
170
+ private mutate;
171
+ private acquireLock;
172
+ private readLedger;
173
+ private readLedgerUnlocked;
174
+ private writeLedgerUnlocked;
175
+ private ensureLedgerExists;
176
+ private invalidateCache;
177
+ }
178
+ //# sourceMappingURL=store.d.ts.map