@treeseed/sdk 0.8.10 → 0.8.11
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/d1-store.js +6 -0
- package/dist/git-runtime.js +4 -2
- package/dist/graph/context-query-contracts.d.ts +48 -0
- package/dist/graph/context-query-contracts.js +126 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +24 -0
- package/dist/operations/agent-tools.d.ts +114 -0
- package/dist/operations/agent-tools.js +183 -0
- package/dist/operations/services/commit-message-provider.js +1 -1
- package/dist/operations/services/hub-provider-launch.js +1 -1
- package/dist/operations/services/runtime-tools.js +1 -1
- package/dist/operations.d.ts +1 -0
- package/dist/operations.js +16 -0
- package/dist/platform/environment.js +5 -0
- package/dist/platform/plugins/constants.js +1 -1
- package/dist/plugin-default.js +1 -1
- package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +1 -1
- package/dist/types/agents.d.ts +12 -0
- package/package.json +9 -1
package/dist/d1-store.js
CHANGED
|
@@ -120,6 +120,9 @@ class MemoryAgentDatabase {
|
|
|
120
120
|
if (model === "task") {
|
|
121
121
|
return [...this.tasks.values()];
|
|
122
122
|
}
|
|
123
|
+
if (model === "task_output") {
|
|
124
|
+
return [...this.taskOutputs.values()].flat();
|
|
125
|
+
}
|
|
123
126
|
if (model === "graph_run") {
|
|
124
127
|
return [...this.graphRuns.values()];
|
|
125
128
|
}
|
|
@@ -160,6 +163,9 @@ class MemoryAgentDatabase {
|
|
|
160
163
|
if (request.model === "task") {
|
|
161
164
|
return this.tasks.get(key) ?? null;
|
|
162
165
|
}
|
|
166
|
+
if (request.model === "task_output") {
|
|
167
|
+
return [...this.taskOutputs.values()].flat().find((output) => output.id === key) ?? null;
|
|
168
|
+
}
|
|
163
169
|
if (request.model === "graph_run") {
|
|
164
170
|
return this.graphRuns.get(key) ?? null;
|
|
165
171
|
}
|
package/dist/git-runtime.js
CHANGED
|
@@ -52,8 +52,10 @@ class GitRuntime {
|
|
|
52
52
|
try {
|
|
53
53
|
await execFileAsync("git", ["commit", "-m", commitMessage], { cwd: worktreePath });
|
|
54
54
|
} catch (error) {
|
|
55
|
-
const
|
|
56
|
-
|
|
55
|
+
const stderr = error && typeof error === "object" && "stderr" in error ? String(error.stderr ?? "") : "";
|
|
56
|
+
const stdout2 = error && typeof error === "object" && "stdout" in error ? String(error.stdout ?? "") : "";
|
|
57
|
+
if (!`${stdout2}
|
|
58
|
+
${stderr}`.includes("nothing to commit")) {
|
|
57
59
|
throw error;
|
|
58
60
|
}
|
|
59
61
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { SdkContextPack, SdkContextPackRequest, SdkGraphQueryStage, SdkGraphQueryView } from '../sdk-types.ts';
|
|
2
|
+
export type DeclarativeContextQueryPurpose = 'plan' | 'research' | 'generate' | 'optimize' | 'implement' | 'review' | 'release' | string;
|
|
3
|
+
export type DeclarativeContextQueryFormat = 'summary' | 'full' | 'sources' | 'list' | 'brief' | 'map' | string;
|
|
4
|
+
export interface DeclarativeContextQuery {
|
|
5
|
+
id: string;
|
|
6
|
+
purpose: DeclarativeContextQueryPurpose;
|
|
7
|
+
query: string;
|
|
8
|
+
scope?: string;
|
|
9
|
+
relations?: string[];
|
|
10
|
+
depth?: number;
|
|
11
|
+
budget?: number;
|
|
12
|
+
format?: DeclarativeContextQueryFormat;
|
|
13
|
+
filters?: Record<string, unknown>;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export type HandlerContextPackSource = 'agent_spec' | 'content_frontmatter' | 'work_package' | 'task_payload' | 'default_role_context';
|
|
17
|
+
export interface DeclarativeContextQuerySourceRef {
|
|
18
|
+
source: HandlerContextPackSource;
|
|
19
|
+
ref?: string;
|
|
20
|
+
priority: number;
|
|
21
|
+
}
|
|
22
|
+
export interface CompiledDeclarativeContextQuery {
|
|
23
|
+
query: DeclarativeContextQuery;
|
|
24
|
+
request: SdkContextPackRequest;
|
|
25
|
+
warnings: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface DeclarativeContextQueryCompileResult {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
compiled: CompiledDeclarativeContextQuery | null;
|
|
30
|
+
errors: string[];
|
|
31
|
+
warnings: string[];
|
|
32
|
+
}
|
|
33
|
+
export interface ResolvedHandlerContextPack {
|
|
34
|
+
id: string;
|
|
35
|
+
purpose: string;
|
|
36
|
+
source: HandlerContextPackSource;
|
|
37
|
+
sourceRef?: string;
|
|
38
|
+
query: DeclarativeContextQuery;
|
|
39
|
+
request: SdkContextPackRequest;
|
|
40
|
+
pack: SdkContextPack;
|
|
41
|
+
warnings: string[];
|
|
42
|
+
}
|
|
43
|
+
export declare function declarativeContextPurposeToGraphStage(purpose: string): SdkGraphQueryStage;
|
|
44
|
+
export declare function declarativeContextFormatToGraphView(format: string | undefined): SdkGraphQueryView;
|
|
45
|
+
export declare function compileDeclarativeContextQuery(query: DeclarativeContextQuery, options?: {
|
|
46
|
+
defaultLimit?: number;
|
|
47
|
+
maxDepth?: number;
|
|
48
|
+
}): DeclarativeContextQueryCompileResult;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const VALID_RELATIONS = [
|
|
2
|
+
"related",
|
|
3
|
+
"depends_on",
|
|
4
|
+
"implements",
|
|
5
|
+
"references",
|
|
6
|
+
"parent",
|
|
7
|
+
"child",
|
|
8
|
+
"supersedes"
|
|
9
|
+
];
|
|
10
|
+
const PURPOSE_TO_STAGE = {
|
|
11
|
+
plan: "plan",
|
|
12
|
+
research: "research",
|
|
13
|
+
implement: "implement",
|
|
14
|
+
debug: "debug",
|
|
15
|
+
review: "review"
|
|
16
|
+
};
|
|
17
|
+
const FORMAT_TO_VIEW = {
|
|
18
|
+
summary: "brief",
|
|
19
|
+
brief: "brief",
|
|
20
|
+
full: "full",
|
|
21
|
+
sources: "list",
|
|
22
|
+
list: "list",
|
|
23
|
+
map: "map"
|
|
24
|
+
};
|
|
25
|
+
function asPositiveInteger(value) {
|
|
26
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0;
|
|
27
|
+
}
|
|
28
|
+
function normalizeString(value) {
|
|
29
|
+
return value.trim();
|
|
30
|
+
}
|
|
31
|
+
function declarativeContextPurposeToGraphStage(purpose) {
|
|
32
|
+
return PURPOSE_TO_STAGE[purpose.trim().toLowerCase()] ?? "plan";
|
|
33
|
+
}
|
|
34
|
+
function declarativeContextFormatToGraphView(format) {
|
|
35
|
+
return FORMAT_TO_VIEW[(format ?? "summary").trim().toLowerCase()] ?? "brief";
|
|
36
|
+
}
|
|
37
|
+
function compileDeclarativeContextQuery(query, options = {}) {
|
|
38
|
+
const errors = [];
|
|
39
|
+
const warnings = [];
|
|
40
|
+
const maxDepth = options.maxDepth ?? 3;
|
|
41
|
+
const defaultLimit = options.defaultLimit ?? 8;
|
|
42
|
+
const id = normalizeString(query.id ?? "");
|
|
43
|
+
if (!id) {
|
|
44
|
+
errors.push("Context query id is required.");
|
|
45
|
+
}
|
|
46
|
+
const purpose = normalizeString(query.purpose ?? "");
|
|
47
|
+
if (!purpose) {
|
|
48
|
+
errors.push(`Context query "${id || "<unknown>"}" purpose is required.`);
|
|
49
|
+
}
|
|
50
|
+
const textQuery = normalizeString(query.query ?? "");
|
|
51
|
+
if (!textQuery) {
|
|
52
|
+
errors.push(`Context query "${id || "<unknown>"}" query is required.`);
|
|
53
|
+
}
|
|
54
|
+
const depth = query.depth ?? 1;
|
|
55
|
+
if (!Number.isInteger(depth) || depth < 0 || depth > maxDepth) {
|
|
56
|
+
errors.push(`Context query "${id || "<unknown>"}" depth must be an integer between 0 and ${maxDepth}.`);
|
|
57
|
+
}
|
|
58
|
+
if (query.budget !== void 0 && !asPositiveInteger(query.budget)) {
|
|
59
|
+
errors.push(`Context query "${id || "<unknown>"}" budget must be a positive integer.`);
|
|
60
|
+
}
|
|
61
|
+
const scope = query.scope === void 0 ? void 0 : normalizeString(query.scope);
|
|
62
|
+
if (scope !== void 0 && (!scope || !scope.startsWith("/"))) {
|
|
63
|
+
errors.push(`Context query "${id || "<unknown>"}" scope must start with "/".`);
|
|
64
|
+
}
|
|
65
|
+
const relations = (query.relations ?? ["related", "references"]).map((entry) => entry.trim().toLowerCase());
|
|
66
|
+
const invalidRelations = relations.filter((relation) => !VALID_RELATIONS.includes(relation));
|
|
67
|
+
if (invalidRelations.length > 0) {
|
|
68
|
+
errors.push(`Context query "${id || "<unknown>"}" has invalid relations: ${invalidRelations.join(", ")}.`);
|
|
69
|
+
}
|
|
70
|
+
const uniqueRelations = [...new Set(relations)];
|
|
71
|
+
if (uniqueRelations.length !== relations.length) {
|
|
72
|
+
warnings.push(`Context query "${id || "<unknown>"}" included duplicate relations; duplicates were removed.`);
|
|
73
|
+
}
|
|
74
|
+
const stage = declarativeContextPurposeToGraphStage(purpose);
|
|
75
|
+
if (stage === "plan" && !["plan", ""].includes(purpose.toLowerCase()) && !PURPOSE_TO_STAGE[purpose.toLowerCase()]) {
|
|
76
|
+
warnings.push(`Context query "${id || "<unknown>"}" purpose "${purpose}" is not a graph stage; using "plan".`);
|
|
77
|
+
}
|
|
78
|
+
const view = declarativeContextFormatToGraphView(query.format);
|
|
79
|
+
if (query.format && !FORMAT_TO_VIEW[query.format.trim().toLowerCase()]) {
|
|
80
|
+
warnings.push(`Context query "${id || "<unknown>"}" format "${query.format}" is not a graph view; using "brief".`);
|
|
81
|
+
}
|
|
82
|
+
if (errors.length > 0) {
|
|
83
|
+
return { ok: false, compiled: null, errors, warnings };
|
|
84
|
+
}
|
|
85
|
+
const request = {
|
|
86
|
+
query: textQuery,
|
|
87
|
+
stage,
|
|
88
|
+
relations: uniqueRelations,
|
|
89
|
+
view,
|
|
90
|
+
options: {
|
|
91
|
+
depth,
|
|
92
|
+
limit: defaultLimit,
|
|
93
|
+
maxNodes: defaultLimit
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
if (scope) {
|
|
97
|
+
request.scopePaths = [scope];
|
|
98
|
+
}
|
|
99
|
+
if (query.budget !== void 0) {
|
|
100
|
+
request.budget = {
|
|
101
|
+
maxTokens: query.budget
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
ok: true,
|
|
106
|
+
compiled: {
|
|
107
|
+
query: {
|
|
108
|
+
...query,
|
|
109
|
+
id,
|
|
110
|
+
purpose,
|
|
111
|
+
query: textQuery,
|
|
112
|
+
scope,
|
|
113
|
+
relations: uniqueRelations
|
|
114
|
+
},
|
|
115
|
+
request,
|
|
116
|
+
warnings
|
|
117
|
+
},
|
|
118
|
+
errors: [],
|
|
119
|
+
warnings
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
compileDeclarativeContextQuery,
|
|
124
|
+
declarativeContextFormatToGraphView,
|
|
125
|
+
declarativeContextPurposeToGraphStage
|
|
126
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { PUBLISHED_CONTENT_MANIFEST_SCHEMA_VERSION, EDITORIAL_PREVIEW_COOKIE, Te
|
|
|
13
13
|
export { createFilesystemContentSource, createPublishedContentPipeline, } from './platform/published-content-pipeline.ts';
|
|
14
14
|
export { loadTreeseedManifest, loadTreeseedTenantManifest, resolveTreeseedTenantRoot, getTenantContentRoot, tenantFeatureEnabled, tenantModelRendered, } from './platform/tenant-config.ts';
|
|
15
15
|
export { parseGraphDsl } from './graph/dsl.ts';
|
|
16
|
+
export { compileDeclarativeContextQuery, declarativeContextFormatToGraphView, declarativeContextPurposeToGraphStage, type CompiledDeclarativeContextQuery, type DeclarativeContextQuery, type DeclarativeContextQueryCompileResult, type DeclarativeContextQueryFormat, type DeclarativeContextQueryPurpose, type DeclarativeContextQuerySourceRef, type HandlerContextPackSource, type ResolvedHandlerContextPack, } from './graph/context-query-contracts.ts';
|
|
16
17
|
export { createDefaultGraphRankingProvider, DEFAULT_GRAPH_RANKING_PROVIDER } from './graph/ranking.ts';
|
|
17
18
|
export { BUILTIN_MODEL_REGISTRY, MODEL_REGISTRY, buildBuiltinModelRegistry, buildModelRegistry, buildScopedModelRegistry, mergeModelRegistries, resolveModelDefinition, } from './model-registry.ts';
|
|
18
19
|
export { normalizeAgentCliOptions, buildCopilotAllowToolArgs } from './cli-tools.ts';
|
|
@@ -20,6 +21,7 @@ export { collectTreeseedDependencyStatus, collectTreeseedToolStatus, createTrees
|
|
|
20
21
|
export { runTreeseedCopilotTask, type TreeseedCopilotTaskInput, type TreeseedCopilotTaskResult, } from './copilot.ts';
|
|
21
22
|
export { findDispatchCapability, listSdkDispatchCapabilities, listWorkflowDispatchCapabilities, } from './dispatch.ts';
|
|
22
23
|
export { executeSdkOperation, findSdkOperation, listSdkOperationNames, } from './sdk-dispatch.ts';
|
|
24
|
+
export { AGENT_OPERATION_MODES, AGENT_OPERATION_NAMES, createAgentOperationEvent, decideAgentOperationPermission, deniedAgentOperationResult, isAgentOperationName, resolveAgentOperationGrant, type AgentDeterministicOperationStep, type AgentOperationApprovalRef, type AgentOperationEvent, type AgentOperationGrant, type AgentOperationMergeFailure, type AgentOperationMode, type AgentOperationName, type AgentOperationPermissionCode, type AgentOperationPermissionDecision, type AgentOperationRequest, type AgentOperationResult, type AgentOperationStatus, } from './operations/agent-tools.ts';
|
|
23
25
|
export { resolveSdkRecordVersion } from './sdk-version.ts';
|
|
24
26
|
export { normalizeAliasedRecord, preprocessAliasedRecord, resolveAliasedField, } from './field-aliases.ts';
|
|
25
27
|
export { canonicalizeFrontmatter, normalizeFilterFields, normalizeMutationData, normalizeRecordToCanonicalShape, normalizeSortFields, readCanonicalFieldValue, resolveModelField, validateModelFieldAliases, } from './sdk-fields.ts';
|
package/dist/index.js
CHANGED
|
@@ -94,6 +94,11 @@ import {
|
|
|
94
94
|
tenantModelRendered
|
|
95
95
|
} from "./platform/tenant-config.js";
|
|
96
96
|
import { parseGraphDsl } from "./graph/dsl.js";
|
|
97
|
+
import {
|
|
98
|
+
compileDeclarativeContextQuery,
|
|
99
|
+
declarativeContextFormatToGraphView,
|
|
100
|
+
declarativeContextPurposeToGraphStage
|
|
101
|
+
} from "./graph/context-query-contracts.js";
|
|
97
102
|
import { createDefaultGraphRankingProvider, DEFAULT_GRAPH_RANKING_PROVIDER } from "./graph/ranking.js";
|
|
98
103
|
import {
|
|
99
104
|
BUILTIN_MODEL_REGISTRY,
|
|
@@ -127,6 +132,15 @@ import {
|
|
|
127
132
|
findSdkOperation,
|
|
128
133
|
listSdkOperationNames
|
|
129
134
|
} from "./sdk-dispatch.js";
|
|
135
|
+
import {
|
|
136
|
+
AGENT_OPERATION_MODES,
|
|
137
|
+
AGENT_OPERATION_NAMES,
|
|
138
|
+
createAgentOperationEvent,
|
|
139
|
+
decideAgentOperationPermission,
|
|
140
|
+
deniedAgentOperationResult,
|
|
141
|
+
isAgentOperationName,
|
|
142
|
+
resolveAgentOperationGrant
|
|
143
|
+
} from "./operations/agent-tools.js";
|
|
130
144
|
import { resolveSdkRecordVersion } from "./sdk-version.js";
|
|
131
145
|
import {
|
|
132
146
|
normalizeAliasedRecord,
|
|
@@ -200,6 +214,8 @@ import { getTreeseedVerifyDriverStatus, runTreeseedVerifyDriver } from "./verifi
|
|
|
200
214
|
import { CloudflareHttpD1Database } from "./d1-http.js";
|
|
201
215
|
export {
|
|
202
216
|
AGENT_MESSAGE_KINDS,
|
|
217
|
+
AGENT_OPERATION_MODES,
|
|
218
|
+
AGENT_OPERATION_NAMES,
|
|
203
219
|
AgentSdk,
|
|
204
220
|
BUILTIN_MODEL_REGISTRY,
|
|
205
221
|
CloudflareHttpD1Database,
|
|
@@ -250,6 +266,8 @@ export {
|
|
|
250
266
|
collectTreeseedDependencyStatus,
|
|
251
267
|
collectTreeseedReconcileStatus,
|
|
252
268
|
collectTreeseedToolStatus,
|
|
269
|
+
compileDeclarativeContextQuery,
|
|
270
|
+
createAgentOperationEvent,
|
|
253
271
|
createControlPlaneReporter,
|
|
254
272
|
createDefaultGraphRankingProvider,
|
|
255
273
|
createFilesystemContentSource,
|
|
@@ -260,7 +278,11 @@ export {
|
|
|
260
278
|
createTeamScopedR2OverlayContentRuntimeProvider,
|
|
261
279
|
createTreeseedManagedToolEnv,
|
|
262
280
|
createTreeseedReconcileRegistry,
|
|
281
|
+
decideAgentOperationPermission,
|
|
282
|
+
declarativeContextFormatToGraphView,
|
|
283
|
+
declarativeContextPurposeToGraphStage,
|
|
263
284
|
defaultHubContentResolutionPolicy,
|
|
285
|
+
deniedAgentOperationResult,
|
|
264
286
|
deriveTreeseedDesiredUnits,
|
|
265
287
|
destroyTreeseedTargetUnits,
|
|
266
288
|
ensureRailwayEnvironment,
|
|
@@ -278,6 +300,7 @@ export {
|
|
|
278
300
|
getTreeseedVerifyDriverStatus,
|
|
279
301
|
importKnowledgePack,
|
|
280
302
|
installTreeseedDependencies,
|
|
303
|
+
isAgentOperationName,
|
|
281
304
|
isTeamScopedR2ContentEnabled,
|
|
282
305
|
listIntegratedMarketCatalog,
|
|
283
306
|
listRailwayEnvironments,
|
|
@@ -320,6 +343,7 @@ export {
|
|
|
320
343
|
removeMarketProfile,
|
|
321
344
|
reservationHasCapacity,
|
|
322
345
|
reserveCreditsForEstimate,
|
|
346
|
+
resolveAgentOperationGrant,
|
|
323
347
|
resolveAliasedField,
|
|
324
348
|
resolveCatalogMarketProfiles,
|
|
325
349
|
resolveCloudflareR2Bucket,
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export declare const AGENT_OPERATION_NAMES: readonly ["switch", "dev", "verify", "save", "stage", "merge_to_staging", "close", "release"];
|
|
2
|
+
export declare const AGENT_OPERATION_MODES: readonly ["dry_run", "read_only", "mutating"];
|
|
3
|
+
export type AgentOperationName = (typeof AGENT_OPERATION_NAMES)[number];
|
|
4
|
+
export type AgentOperationMode = (typeof AGENT_OPERATION_MODES)[number];
|
|
5
|
+
export type AgentOperationStatus = 'completed' | 'waiting' | 'failed' | 'skipped' | 'retry_created';
|
|
6
|
+
export interface AgentOperationApprovalRef {
|
|
7
|
+
id: string;
|
|
8
|
+
kind?: string;
|
|
9
|
+
state: 'pending' | 'approved' | 'rejected' | 'expired' | 'superseded';
|
|
10
|
+
}
|
|
11
|
+
export interface AgentOperationRequest {
|
|
12
|
+
operation: AgentOperationName;
|
|
13
|
+
mode: AgentOperationMode;
|
|
14
|
+
taskId: string;
|
|
15
|
+
taskKind?: string;
|
|
16
|
+
workDayId?: string;
|
|
17
|
+
agentSlug: string;
|
|
18
|
+
agentRole: string;
|
|
19
|
+
projectId: string;
|
|
20
|
+
environment: string;
|
|
21
|
+
repoRoot: string;
|
|
22
|
+
worktreeRoot?: string;
|
|
23
|
+
featureBranch?: string;
|
|
24
|
+
stagingBranch?: string;
|
|
25
|
+
approvalId?: string;
|
|
26
|
+
approval?: AgentOperationApprovalRef;
|
|
27
|
+
permissionGrantId?: string;
|
|
28
|
+
allowedPaths?: string[];
|
|
29
|
+
forbiddenPaths?: string[];
|
|
30
|
+
changedPaths?: string[];
|
|
31
|
+
input: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
export interface AgentDeterministicOperationStep {
|
|
34
|
+
id: string;
|
|
35
|
+
operation: AgentOperationName;
|
|
36
|
+
stage: 'before_mutation' | 'during_mutation' | 'after_mutation' | 'after_verification_passes' | 'after_verification_fails' | 'after_staging_merge_fails' | 'closeout' | string;
|
|
37
|
+
mode: AgentOperationMode;
|
|
38
|
+
required?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface AgentOperationGrant {
|
|
41
|
+
id: string;
|
|
42
|
+
state?: 'active' | 'paused' | 'revoked';
|
|
43
|
+
operations: AgentOperationName[];
|
|
44
|
+
modes: AgentOperationMode[];
|
|
45
|
+
agentRoles?: string[];
|
|
46
|
+
taskKinds?: string[];
|
|
47
|
+
projectIds?: string[];
|
|
48
|
+
environments?: string[];
|
|
49
|
+
allowedPaths?: string[];
|
|
50
|
+
forbiddenPaths?: string[];
|
|
51
|
+
requiresApproval?: boolean;
|
|
52
|
+
approvalIds?: string[];
|
|
53
|
+
expiresAt?: string;
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
export interface AgentOperationMergeFailure {
|
|
57
|
+
targetBranch: string;
|
|
58
|
+
featureBranch: string;
|
|
59
|
+
conflictedPaths: string[];
|
|
60
|
+
message: string;
|
|
61
|
+
repairTaskId?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface AgentOperationResult {
|
|
64
|
+
operation: AgentOperationName;
|
|
65
|
+
status: AgentOperationStatus;
|
|
66
|
+
summary: string;
|
|
67
|
+
changedPaths: string[];
|
|
68
|
+
stagedPaths: string[];
|
|
69
|
+
mergedToStaging?: boolean;
|
|
70
|
+
mergeFailure?: AgentOperationMergeFailure;
|
|
71
|
+
commandsRun: string[];
|
|
72
|
+
artifacts: Array<{
|
|
73
|
+
kind: string;
|
|
74
|
+
ref: string;
|
|
75
|
+
}>;
|
|
76
|
+
error?: {
|
|
77
|
+
code: string;
|
|
78
|
+
message: string;
|
|
79
|
+
retryable: boolean;
|
|
80
|
+
};
|
|
81
|
+
metadata: Record<string, unknown>;
|
|
82
|
+
}
|
|
83
|
+
export type AgentOperationPermissionCode = 'allowed' | 'invalid_operation' | 'operation_permission_required' | 'operation_grant_inactive' | 'operation_grant_expired' | 'operation_mode_not_granted' | 'operation_role_not_granted' | 'operation_task_kind_not_granted' | 'operation_project_not_granted' | 'operation_environment_not_granted' | 'operation_approval_required' | 'operation_release_approval_required' | 'operation_worktree_required' | 'operation_allowed_paths_required' | 'operation_path_not_allowed' | 'operation_path_forbidden';
|
|
84
|
+
export interface AgentOperationPermissionDecision {
|
|
85
|
+
allowed: boolean;
|
|
86
|
+
status: 'completed' | 'waiting' | 'failed';
|
|
87
|
+
code: AgentOperationPermissionCode;
|
|
88
|
+
summary: string;
|
|
89
|
+
grant?: AgentOperationGrant;
|
|
90
|
+
metadata: Record<string, unknown>;
|
|
91
|
+
}
|
|
92
|
+
export interface AgentOperationEvent {
|
|
93
|
+
operation: AgentOperationName;
|
|
94
|
+
mode: AgentOperationMode;
|
|
95
|
+
agentRole: string;
|
|
96
|
+
taskId: string;
|
|
97
|
+
permissionGrantId?: string;
|
|
98
|
+
inputSummary: Record<string, unknown>;
|
|
99
|
+
result: AgentOperationResult;
|
|
100
|
+
createdAt: string;
|
|
101
|
+
}
|
|
102
|
+
export declare function isAgentOperationName(value: string): value is AgentOperationName;
|
|
103
|
+
export declare function resolveAgentOperationGrant(request: AgentOperationRequest, grants: readonly AgentOperationGrant[], now?: Date): AgentOperationGrant | null;
|
|
104
|
+
export declare function decideAgentOperationPermission(input: {
|
|
105
|
+
request: AgentOperationRequest;
|
|
106
|
+
grants: readonly AgentOperationGrant[];
|
|
107
|
+
now?: Date;
|
|
108
|
+
}): AgentOperationPermissionDecision;
|
|
109
|
+
export declare function deniedAgentOperationResult(request: AgentOperationRequest, decision: AgentOperationPermissionDecision): AgentOperationResult;
|
|
110
|
+
export declare function createAgentOperationEvent(input: {
|
|
111
|
+
request: AgentOperationRequest;
|
|
112
|
+
result: AgentOperationResult;
|
|
113
|
+
createdAt?: string;
|
|
114
|
+
}): AgentOperationEvent;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
const AGENT_OPERATION_NAMES = [
|
|
2
|
+
"switch",
|
|
3
|
+
"dev",
|
|
4
|
+
"verify",
|
|
5
|
+
"save",
|
|
6
|
+
"stage",
|
|
7
|
+
"merge_to_staging",
|
|
8
|
+
"close",
|
|
9
|
+
"release"
|
|
10
|
+
];
|
|
11
|
+
const AGENT_OPERATION_MODES = ["dry_run", "read_only", "mutating"];
|
|
12
|
+
function normalizePath(value) {
|
|
13
|
+
return value.replace(/\\/gu, "/").replace(/^\.?\//u, "").replace(/\/+/gu, "/");
|
|
14
|
+
}
|
|
15
|
+
function matchesPattern(path, pattern) {
|
|
16
|
+
const normalizedPath = normalizePath(path);
|
|
17
|
+
const normalizedPattern = normalizePath(pattern);
|
|
18
|
+
if (normalizedPattern.endsWith("/**")) {
|
|
19
|
+
const prefix = normalizedPattern.slice(0, -3);
|
|
20
|
+
return normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`);
|
|
21
|
+
}
|
|
22
|
+
if (normalizedPattern.endsWith("/")) {
|
|
23
|
+
return normalizedPath.startsWith(normalizedPattern);
|
|
24
|
+
}
|
|
25
|
+
return normalizedPath === normalizedPattern || normalizedPath.startsWith(`${normalizedPattern}/`);
|
|
26
|
+
}
|
|
27
|
+
function listMatches(value, allowed) {
|
|
28
|
+
return !allowed?.length || value !== void 0 && allowed.includes(value);
|
|
29
|
+
}
|
|
30
|
+
function grantActive(grant, now) {
|
|
31
|
+
if ((grant.state ?? "active") !== "active") {
|
|
32
|
+
return "operation_grant_inactive";
|
|
33
|
+
}
|
|
34
|
+
if (grant.expiresAt && Date.parse(grant.expiresAt) <= now.valueOf()) {
|
|
35
|
+
return "operation_grant_expired";
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
function deny(code, summary, options = {}) {
|
|
40
|
+
return {
|
|
41
|
+
allowed: false,
|
|
42
|
+
status: options.status ?? "waiting",
|
|
43
|
+
code,
|
|
44
|
+
summary,
|
|
45
|
+
grant: options.grant,
|
|
46
|
+
metadata: options.metadata ?? {}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function allow(grant, metadata = {}) {
|
|
50
|
+
return {
|
|
51
|
+
allowed: true,
|
|
52
|
+
status: "completed",
|
|
53
|
+
code: "allowed",
|
|
54
|
+
summary: `Operation grant ${grant.id} allows this request.`,
|
|
55
|
+
grant,
|
|
56
|
+
metadata
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function isAgentOperationName(value) {
|
|
60
|
+
return AGENT_OPERATION_NAMES.includes(value);
|
|
61
|
+
}
|
|
62
|
+
function resolveAgentOperationGrant(request, grants, now = /* @__PURE__ */ new Date()) {
|
|
63
|
+
return grants.find((grant) => {
|
|
64
|
+
if (request.permissionGrantId && grant.id !== request.permissionGrantId) return false;
|
|
65
|
+
if (grantActive(grant, now)) return false;
|
|
66
|
+
if (!grant.operations.includes(request.operation)) return false;
|
|
67
|
+
return true;
|
|
68
|
+
}) ?? null;
|
|
69
|
+
}
|
|
70
|
+
function decideAgentOperationPermission(input) {
|
|
71
|
+
const { request } = input;
|
|
72
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
73
|
+
if (!isAgentOperationName(request.operation)) {
|
|
74
|
+
return deny("invalid_operation", `Unsupported agent operation "${String(request.operation)}".`, { status: "failed" });
|
|
75
|
+
}
|
|
76
|
+
if (request.operation === "release") {
|
|
77
|
+
const approval = request.approval;
|
|
78
|
+
if (!approval || approval.state !== "approved" || request.approvalId && approval.id !== request.approvalId) {
|
|
79
|
+
return deny("operation_release_approval_required", "Release requires an explicit approved release approval.");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const grant = resolveAgentOperationGrant(request, input.grants, now);
|
|
83
|
+
if (!grant) {
|
|
84
|
+
return deny("operation_permission_required", `No operation grant allows ${request.agentRole} to run ${request.operation}.`);
|
|
85
|
+
}
|
|
86
|
+
const activeCode = grantActive(grant, now);
|
|
87
|
+
if (activeCode) {
|
|
88
|
+
return deny(activeCode, `Operation grant ${grant.id} is not active.`, { grant });
|
|
89
|
+
}
|
|
90
|
+
if (!grant.modes.includes(request.mode)) {
|
|
91
|
+
return deny("operation_mode_not_granted", `Operation grant ${grant.id} does not allow ${request.mode} mode.`, { grant });
|
|
92
|
+
}
|
|
93
|
+
if (!listMatches(request.agentRole, grant.agentRoles)) {
|
|
94
|
+
return deny("operation_role_not_granted", `Operation grant ${grant.id} does not allow role ${request.agentRole}.`, { grant });
|
|
95
|
+
}
|
|
96
|
+
if (!listMatches(request.taskKind, grant.taskKinds)) {
|
|
97
|
+
return deny("operation_task_kind_not_granted", `Operation grant ${grant.id} does not allow task kind ${request.taskKind ?? "<none>"}.`, { grant });
|
|
98
|
+
}
|
|
99
|
+
if (!listMatches(request.projectId, grant.projectIds)) {
|
|
100
|
+
return deny("operation_project_not_granted", `Operation grant ${grant.id} does not allow project ${request.projectId}.`, { grant });
|
|
101
|
+
}
|
|
102
|
+
if (!listMatches(request.environment, grant.environments)) {
|
|
103
|
+
return deny("operation_environment_not_granted", `Operation grant ${grant.id} does not allow environment ${request.environment}.`, { grant });
|
|
104
|
+
}
|
|
105
|
+
if (grant.requiresApproval && (!request.approval || request.approval.state !== "approved")) {
|
|
106
|
+
return deny("operation_approval_required", `Operation grant ${grant.id} requires approval.`, { grant });
|
|
107
|
+
}
|
|
108
|
+
if (grant.approvalIds?.length && (!request.approval || !grant.approvalIds.includes(request.approval.id) || request.approval.state !== "approved")) {
|
|
109
|
+
return deny("operation_approval_required", `Operation grant ${grant.id} requires one of its approved approval ids.`, { grant });
|
|
110
|
+
}
|
|
111
|
+
if (request.mode === "mutating" && !request.worktreeRoot && request.operation !== "release") {
|
|
112
|
+
return deny("operation_worktree_required", `Mutating operation ${request.operation} requires an assigned worktree root.`, { grant });
|
|
113
|
+
}
|
|
114
|
+
const allowedPaths = request.allowedPaths?.length ? request.allowedPaths : grant.allowedPaths ?? [];
|
|
115
|
+
const forbiddenPaths = [...grant.forbiddenPaths ?? [], ...request.forbiddenPaths ?? []];
|
|
116
|
+
const changedPaths = request.changedPaths ?? [];
|
|
117
|
+
if ((request.operation === "stage" || request.operation === "merge_to_staging") && allowedPaths.length === 0) {
|
|
118
|
+
return deny("operation_allowed_paths_required", `${request.operation} requires allowed paths.`, { grant });
|
|
119
|
+
}
|
|
120
|
+
for (const changedPath of changedPaths) {
|
|
121
|
+
if (forbiddenPaths.some((pattern) => matchesPattern(changedPath, pattern))) {
|
|
122
|
+
return deny("operation_path_forbidden", `${changedPath} is forbidden.`, {
|
|
123
|
+
grant,
|
|
124
|
+
status: "failed",
|
|
125
|
+
metadata: { changedPath, forbiddenPaths }
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (allowedPaths.length > 0 && !allowedPaths.some((pattern) => matchesPattern(changedPath, pattern))) {
|
|
129
|
+
return deny("operation_path_not_allowed", `${changedPath} is outside allowed paths.`, {
|
|
130
|
+
grant,
|
|
131
|
+
status: "failed",
|
|
132
|
+
metadata: { changedPath, allowedPaths }
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return allow(grant, { allowedPaths, forbiddenPaths });
|
|
137
|
+
}
|
|
138
|
+
function deniedAgentOperationResult(request, decision) {
|
|
139
|
+
return {
|
|
140
|
+
operation: request.operation,
|
|
141
|
+
status: decision.status,
|
|
142
|
+
summary: decision.summary,
|
|
143
|
+
changedPaths: request.changedPaths ?? [],
|
|
144
|
+
stagedPaths: [],
|
|
145
|
+
commandsRun: [],
|
|
146
|
+
artifacts: [],
|
|
147
|
+
error: {
|
|
148
|
+
code: decision.code,
|
|
149
|
+
message: decision.summary,
|
|
150
|
+
retryable: decision.status === "waiting"
|
|
151
|
+
},
|
|
152
|
+
metadata: {
|
|
153
|
+
permission: decision
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function createAgentOperationEvent(input) {
|
|
158
|
+
return {
|
|
159
|
+
operation: input.request.operation,
|
|
160
|
+
mode: input.request.mode,
|
|
161
|
+
agentRole: input.request.agentRole,
|
|
162
|
+
taskId: input.request.taskId,
|
|
163
|
+
permissionGrantId: input.request.permissionGrantId,
|
|
164
|
+
inputSummary: {
|
|
165
|
+
projectId: input.request.projectId,
|
|
166
|
+
environment: input.request.environment,
|
|
167
|
+
allowedPaths: input.request.allowedPaths ?? [],
|
|
168
|
+
forbiddenPaths: input.request.forbiddenPaths ?? [],
|
|
169
|
+
changedPaths: input.request.changedPaths ?? []
|
|
170
|
+
},
|
|
171
|
+
result: input.result,
|
|
172
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
export {
|
|
176
|
+
AGENT_OPERATION_MODES,
|
|
177
|
+
AGENT_OPERATION_NAMES,
|
|
178
|
+
createAgentOperationEvent,
|
|
179
|
+
decideAgentOperationPermission,
|
|
180
|
+
deniedAgentOperationResult,
|
|
181
|
+
isAgentOperationName,
|
|
182
|
+
resolveAgentOperationGrant
|
|
183
|
+
};
|
|
@@ -352,7 +352,7 @@ function applyManagedProjectDefaults(projectRoot, input) {
|
|
|
352
352
|
...config.providers ?? {},
|
|
353
353
|
forms: config.providers?.forms ?? "store_only",
|
|
354
354
|
agents: {
|
|
355
|
-
execution: "
|
|
355
|
+
execution: "codex",
|
|
356
356
|
mutation: "local_branch",
|
|
357
357
|
repository: "git",
|
|
358
358
|
verification: "local",
|
package/dist/operations.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export { TreeseedOperationsSdk } from './operations/runtime.ts';
|
|
|
5
5
|
export type { HubContentResolutionPolicy, KnowledgeHubLaunchIntent, KnowledgeHubLaunchPhase, KnowledgeHubLaunchPlan, KnowledgeHubLaunchResult, KnowledgeHubRepositoryPlan, RepositoryHost, } from './operations/services/hub-launch.ts';
|
|
6
6
|
export type { TreeseedOperationContext, TreeseedOperationImplementation, TreeseedOperationId, TreeseedOperationMetadata, TreeseedOperationProvider, TreeseedOperationProviderId, TreeseedOperationRequest, TreeseedOperationResult, TreeseedOperationGroup, } from './operations-types.ts';
|
|
7
7
|
export { TreeseedOperationError } from './operations-types.ts';
|
|
8
|
+
export { AGENT_OPERATION_MODES, AGENT_OPERATION_NAMES, createAgentOperationEvent, decideAgentOperationPermission, deniedAgentOperationResult, isAgentOperationName, resolveAgentOperationGrant, type AgentDeterministicOperationStep, type AgentOperationApprovalRef, type AgentOperationEvent, type AgentOperationGrant, type AgentOperationMergeFailure, type AgentOperationMode, type AgentOperationName, type AgentOperationPermissionCode, type AgentOperationPermissionDecision, type AgentOperationRequest, type AgentOperationResult, type AgentOperationStatus, } from './operations/agent-tools.ts';
|
|
8
9
|
export { TreeseedWorkflowSdk } from './workflow.ts';
|
|
9
10
|
export type * from './workflow.ts';
|
package/dist/operations.js
CHANGED
|
@@ -15,20 +15,36 @@ import {
|
|
|
15
15
|
} from "./operations/services/hub-launch.js";
|
|
16
16
|
import { TreeseedOperationsSdk } from "./operations/runtime.js";
|
|
17
17
|
import { TreeseedOperationError } from "./operations-types.js";
|
|
18
|
+
import {
|
|
19
|
+
AGENT_OPERATION_MODES,
|
|
20
|
+
AGENT_OPERATION_NAMES,
|
|
21
|
+
createAgentOperationEvent,
|
|
22
|
+
decideAgentOperationPermission,
|
|
23
|
+
deniedAgentOperationResult,
|
|
24
|
+
isAgentOperationName,
|
|
25
|
+
resolveAgentOperationGrant
|
|
26
|
+
} from "./operations/agent-tools.js";
|
|
18
27
|
import { TreeseedWorkflowSdk } from "./workflow.js";
|
|
19
28
|
export {
|
|
29
|
+
AGENT_OPERATION_MODES,
|
|
30
|
+
AGENT_OPERATION_NAMES,
|
|
20
31
|
TRESEED_OPERATION_SPECS,
|
|
21
32
|
TreeseedOperationError,
|
|
22
33
|
TreeseedOperationsSdk,
|
|
23
34
|
TreeseedWorkflowSdk,
|
|
24
35
|
collectTreeseedConfigSeedValues,
|
|
36
|
+
createAgentOperationEvent,
|
|
25
37
|
createKnowledgeHubRepositories,
|
|
38
|
+
decideAgentOperationPermission,
|
|
26
39
|
defaultHubContentResolutionPolicy,
|
|
40
|
+
deniedAgentOperationResult,
|
|
27
41
|
executeKnowledgeHubLaunch,
|
|
28
42
|
findTreeseedOperation,
|
|
43
|
+
isAgentOperationName,
|
|
29
44
|
listTreeseedOperationNames,
|
|
30
45
|
normalizeKnowledgeHubLaunchIntent,
|
|
31
46
|
planKnowledgeHubLaunch,
|
|
32
47
|
planKnowledgeHubRepositories,
|
|
48
|
+
resolveAgentOperationGrant,
|
|
33
49
|
validateRepositoryHost
|
|
34
50
|
};
|
|
@@ -106,6 +106,10 @@ function processingPlaneEnabled(context) {
|
|
|
106
106
|
function formsEnabled(context) {
|
|
107
107
|
return webSurfaceEnabled(context) && (context.deployConfig.providers?.forms ?? "store_only") !== "none";
|
|
108
108
|
}
|
|
109
|
+
function codexExecutionSelected(context) {
|
|
110
|
+
const execution = context.deployConfig.providers?.agents?.execution ?? "codex";
|
|
111
|
+
return execution === "codex" || execution === "codex_subscription";
|
|
112
|
+
}
|
|
109
113
|
function railwayManagedEnabled(context) {
|
|
110
114
|
if (!workflowPlaneAllows("processing")) {
|
|
111
115
|
return false;
|
|
@@ -333,6 +337,7 @@ const PREDICATES = {
|
|
|
333
337
|
apiSurfaceEnabled: (context) => apiSurfaceEnabled(context),
|
|
334
338
|
processingPlaneEnabled: (context) => processingPlaneEnabled(context),
|
|
335
339
|
formsEnabled: (context) => formsEnabled(context),
|
|
340
|
+
codexExecutionSelected: (context) => codexExecutionSelected(context),
|
|
336
341
|
railwayManagedEnabled: (context) => railwayManagedEnabled(context),
|
|
337
342
|
hubTreeseedHosted: (context) => resolveHubMode(context) === "treeseed_hosted",
|
|
338
343
|
hubCustomerHosted: (context) => resolveHubMode(context) === "customer_hosted",
|
package/dist/plugin-default.js
CHANGED
|
@@ -6,7 +6,7 @@ var plugin_default_default = defineTreeseedPlugin({
|
|
|
6
6
|
forms: ["store_only", "notify_admin", "full_email"],
|
|
7
7
|
operations: ["default"],
|
|
8
8
|
agents: {
|
|
9
|
-
execution: ["stub", "manual", "copilot"],
|
|
9
|
+
execution: ["stub", "manual", "copilot", "codex", "codex_subscription"],
|
|
10
10
|
mutation: ["local_branch"],
|
|
11
11
|
repository: ["stub", "git"],
|
|
12
12
|
verification: ["stub", "local"],
|
package/dist/types/agents.d.ts
CHANGED
|
@@ -27,6 +27,18 @@ export interface AgentOutputContract {
|
|
|
27
27
|
modelMutations: string[];
|
|
28
28
|
}
|
|
29
29
|
export interface AgentExecutionConfig {
|
|
30
|
+
provider?: string;
|
|
31
|
+
model?: string;
|
|
32
|
+
approvalPolicy?: 'never' | 'on_request' | 'always' | string;
|
|
33
|
+
sandboxMode?: 'read_only' | 'workspace_write' | string;
|
|
34
|
+
reasoningEffort?: 'low' | 'medium' | 'high' | string;
|
|
35
|
+
allowedPaths?: string[];
|
|
36
|
+
forbiddenPaths?: string[];
|
|
37
|
+
worktree?: {
|
|
38
|
+
enabled?: boolean;
|
|
39
|
+
root?: string;
|
|
40
|
+
branchPrefix?: string;
|
|
41
|
+
};
|
|
30
42
|
maxConcurrency: number;
|
|
31
43
|
timeoutSeconds: number;
|
|
32
44
|
cooldownSeconds: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.11",
|
|
4
4
|
"description": "Shared Treeseed SDK for content-backed and D1-backed object models.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -96,6 +96,10 @@
|
|
|
96
96
|
"types": "./dist/operations.d.ts",
|
|
97
97
|
"default": "./dist/operations.js"
|
|
98
98
|
},
|
|
99
|
+
"./operations/agent-tools": {
|
|
100
|
+
"types": "./dist/operations/agent-tools.d.ts",
|
|
101
|
+
"default": "./dist/operations/agent-tools.js"
|
|
102
|
+
},
|
|
99
103
|
"./workflow": {
|
|
100
104
|
"types": "./dist/workflow.d.ts",
|
|
101
105
|
"default": "./dist/workflow.js"
|
|
@@ -197,6 +201,10 @@
|
|
|
197
201
|
"types": "./dist/graph.d.ts",
|
|
198
202
|
"default": "./dist/graph.js"
|
|
199
203
|
},
|
|
204
|
+
"./graph/context-query-contracts": {
|
|
205
|
+
"types": "./dist/graph/context-query-contracts.d.ts",
|
|
206
|
+
"default": "./dist/graph/context-query-contracts.js"
|
|
207
|
+
},
|
|
200
208
|
"./sdk-filters": {
|
|
201
209
|
"types": "./dist/sdk-filters.d.ts",
|
|
202
210
|
"default": "./dist/sdk-filters.js"
|