openclaw-engram 3.9.1 → 7.0.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/README.md +15 -2
- package/dist/client.d.ts +18 -36
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +24 -304
- package/dist/client.js.map +1 -1
- package/dist/commands/remember.d.ts.map +1 -1
- package/dist/commands/remember.js +1 -1
- package/dist/commands/remember.js.map +1 -1
- package/dist/config.d.ts +0 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -8
- package/dist/config.js.map +1 -1
- package/dist/hooks/after-tool-call.js +1 -1
- package/dist/hooks/after-tool-call.js.map +1 -1
- package/dist/hooks/before-agent-start.d.ts.map +1 -1
- package/dist/hooks/before-agent-start.js +2 -2
- package/dist/hooks/before-agent-start.js.map +1 -1
- package/dist/hooks/before-compaction.js +1 -1
- package/dist/hooks/before-compaction.js.map +1 -1
- package/dist/hooks/before-prompt-build.js +1 -1
- package/dist/hooks/before-prompt-build.js.map +1 -1
- package/dist/hooks/before-tool-call.js +1 -1
- package/dist/hooks/before-tool-call.js.map +1 -1
- package/dist/hooks/session-end.js +1 -1
- package/dist/hooks/session-end.js.map +1 -1
- package/dist/hooks/session-start.js +1 -1
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/identity.d.ts +8 -52
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +39 -368
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/dist/services/file-watcher.d.ts.map +1 -1
- package/dist/services/file-watcher.js +1 -1
- package/dist/services/file-watcher.js.map +1 -1
- package/dist/tools/engram-decisions.js +1 -1
- package/dist/tools/engram-decisions.js.map +1 -1
- package/dist/tools/engram-issues.js +1 -1
- package/dist/tools/engram-issues.js.map +1 -1
- package/dist/tools/engram-presets.js +1 -1
- package/dist/tools/engram-presets.js.map +1 -1
- package/dist/tools/engram-remember.js +1 -1
- package/dist/tools/engram-remember.js.map +1 -1
- package/dist/tools/engram-search.js +1 -1
- package/dist/tools/engram-search.js.map +1 -1
- package/dist/tools/engram-timeline.js +1 -1
- package/dist/tools/engram-timeline.js.map +1 -1
- package/dist/tools/engram-vault.d.ts +1 -1
- package/dist/tools/engram-vault.d.ts.map +1 -1
- package/dist/tools/engram-vault.js +25 -6
- package/dist/tools/engram-vault.js.map +1 -1
- package/dist/tools/memory-get.js +2 -2
- package/dist/tools/memory-get.js.map +1 -1
- package/dist/tools/memory-migrate.js +1 -1
- package/dist/tools/memory-migrate.js.map +1 -1
- package/openclaw.plugin.json +3 -6
- package/package.json +1 -1
- package/dist/project-identity-v3.d.ts +0 -49
- package/dist/project-identity-v3.d.ts.map +0 -1
- package/dist/project-identity-v3.js +0 -228
- package/dist/project-identity-v3.js.map +0 -1
- package/dist/project-identity-v3.test.d.ts +0 -2
- package/dist/project-identity-v3.test.d.ts.map +0 -1
- package/dist/project-identity-v3.test.js +0 -160
- package/dist/project-identity-v3.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,6 +7,9 @@ OpenClaw plugin that connects agents to an [engram](https://github.com/thebtf/en
|
|
|
7
7
|
- OpenClaw gateway installed and running
|
|
8
8
|
- Engram server running and reachable (default port `37777`)
|
|
9
9
|
- An API token configured on the engram server
|
|
10
|
+
- The matching release Go client (`engram`) on PATH, or its absolute executable
|
|
11
|
+
selected with `ENGRAM_EXECUTABLE`. It must support
|
|
12
|
+
`project resolve --root <actual-workspace> --json`; no JS/TS identity fallback exists.
|
|
10
13
|
|
|
11
14
|
## Installation
|
|
12
15
|
|
|
@@ -67,8 +70,7 @@ All fields are set under `plugins.entries.engram.config`:
|
|
|
67
70
|
|---|---|---|---|
|
|
68
71
|
| `url` | string | `http://localhost:37777` | Engram server base URL |
|
|
69
72
|
| `token` | string | *(required)* | Bearer token for API authentication |
|
|
70
|
-
| `project` | string | *(
|
|
71
|
-
| `clientInstanceId` | string | *(optional)* | Opaque non-secret installation reference that enables V3 identity |
|
|
73
|
+
| `project` | string | *(current workspace)* | Explicit logical project UUID override, never an agent/name/path selector |
|
|
72
74
|
| `contextLimit` | number | `10` | Maximum observations injected per prompt turn |
|
|
73
75
|
| `sessionContextLimit` | number | `20` | Maximum observations injected at session start |
|
|
74
76
|
| `tokenBudget` | number | `2000` | Token budget for context injection (~4 chars/token) |
|
|
@@ -77,6 +79,17 @@ All fields are set under `plugins.entries.engram.config`:
|
|
|
77
79
|
| `workspaceDir` | string | `~/.openclaw/workspace/` | Workspace path for `/migrate` when called from channel context (Telegram, Discord) |
|
|
78
80
|
| `logLevel` | string | `warn` | Log verbosity: `debug`, `info`, `warn`, `error` |
|
|
79
81
|
|
|
82
|
+
Project resolution reads the portable `.engram-project` UUID or the real Git
|
|
83
|
+
common-dir binding through the Go client. Initialize only an explicitly selected
|
|
84
|
+
new project with `engram project init`; carry the marker into independent clones.
|
|
85
|
+
Project-scoped hooks and tools use their current `ctx.workspaceDir` or a configured
|
|
86
|
+
`project` UUID override. Missing or invalid project context returns a scoped error
|
|
87
|
+
without registration/capability roundtrips or changes to the OpenClaw host.
|
|
88
|
+
Explicit global Vault calls do not require project context. Channel `/migrate`
|
|
89
|
+
uses the configured `workspaceDir` or the documented `~/.openclaw/workspace/`
|
|
90
|
+
default. Before importing, it resolves that workspace through the Go client unless
|
|
91
|
+
a valid `project` UUID override is configured.
|
|
92
|
+
|
|
80
93
|
## What it provides
|
|
81
94
|
|
|
82
95
|
### Hooks
|
package/dist/client.d.ts
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { AvailabilityTracker } from './availability.js';
|
|
8
8
|
import type { PluginConfig } from './config.js';
|
|
9
|
-
import { type ProjectIdentity
|
|
10
|
-
import { type ProjectIdentityV3 } from './project-identity-v3.js';
|
|
9
|
+
import { type ProjectIdentity } from './identity.js';
|
|
11
10
|
export interface Observation {
|
|
12
11
|
id: number;
|
|
13
12
|
title: string;
|
|
@@ -93,16 +92,11 @@ export interface BulkImportResponse {
|
|
|
93
92
|
export interface BulkDeleteResponse {
|
|
94
93
|
deleted: number;
|
|
95
94
|
}
|
|
96
|
-
export interface
|
|
95
|
+
export interface ProjectResolutionSuccess {
|
|
97
96
|
ok: true;
|
|
98
97
|
canonicalProject: string;
|
|
99
98
|
}
|
|
100
|
-
export interface
|
|
101
|
-
projectSelector: string;
|
|
102
|
-
projectIdentityV2?: ProjectIdentityV2;
|
|
103
|
-
projectIdentityV3?: ProjectIdentityV3;
|
|
104
|
-
}
|
|
105
|
-
export interface ProjectRegistrationFailure {
|
|
99
|
+
export interface ProjectResolutionFailure {
|
|
106
100
|
ok: false;
|
|
107
101
|
error: {
|
|
108
102
|
code: string;
|
|
@@ -111,8 +105,7 @@ export interface ProjectRegistrationFailure {
|
|
|
111
105
|
httpStatus: number;
|
|
112
106
|
};
|
|
113
107
|
}
|
|
114
|
-
export type
|
|
115
|
-
export type ResolvedProjectRegistrationResult = ResolvedProjectRegistrationSuccess | ProjectRegistrationFailure;
|
|
108
|
+
export type ProjectResolutionResult = ProjectResolutionSuccess | ProjectResolutionFailure;
|
|
116
109
|
export interface OutcomeRetirement {
|
|
117
110
|
contract_version: 'engram.outcome-retirement.v1';
|
|
118
111
|
code: 'OUTCOME_CALLBACK_RETIRED';
|
|
@@ -120,15 +113,10 @@ export interface OutcomeRetirement {
|
|
|
120
113
|
}
|
|
121
114
|
export type OutcomeRecordingResult = boolean | OutcomeRetirement;
|
|
122
115
|
export declare function isOutcomeRetirement(result: OutcomeRecordingResult): result is OutcomeRetirement;
|
|
123
|
-
export interface
|
|
124
|
-
|
|
125
|
-
readonly clientInstanceId?: string;
|
|
116
|
+
export interface ProjectResolverClient {
|
|
117
|
+
resolveWorkspaceProject(agentId: string, workspaceDir?: string): Promise<ProjectIdentity>;
|
|
126
118
|
}
|
|
127
|
-
|
|
128
|
-
* Register an explicit project override as a selector-only shared scope.
|
|
129
|
-
* Without an override, resolve and register the workspace's full identity.
|
|
130
|
-
*/
|
|
131
|
-
export declare function resolveAndRegisterProject(client: ProjectRegistrationClient, agentId: string, workspaceDir: string | undefined, configuredProject?: string): Promise<ResolvedProjectRegistrationResult>;
|
|
119
|
+
export declare function resolveProject(client: ProjectResolverClient, agentId: string, workspaceDir: string | undefined, configuredProject?: string): Promise<ProjectResolutionResult>;
|
|
132
120
|
/** A single observation returned by the decisions search endpoint. */
|
|
133
121
|
export interface DecisionSearchObservation {
|
|
134
122
|
title?: string;
|
|
@@ -195,28 +183,14 @@ export declare class EngramRestClient {
|
|
|
195
183
|
private readonly baseUrl;
|
|
196
184
|
private readonly token;
|
|
197
185
|
private readonly defaultTimeoutMs;
|
|
198
|
-
private readonly completedProjectRegistrations;
|
|
199
|
-
private readonly inFlightProjectRegistrations;
|
|
200
|
-
private readonly v3ContextDescriptors;
|
|
201
186
|
readonly availability: AvailabilityTracker;
|
|
202
|
-
readonly clientInstanceId?: string;
|
|
203
187
|
constructor(config: PluginConfig);
|
|
204
|
-
|
|
205
|
-
* Registration barrier for every project-scoped OpenClaw access.
|
|
206
|
-
*
|
|
207
|
-
* The full identity and outer compatibility selector are resolved before a
|
|
208
|
-
* caller sends its first data request. Concurrent and late calls reuse the
|
|
209
|
-
* same result. Project metadata routes a namespace; the bearer header remains
|
|
210
|
-
* the independent authorization gate.
|
|
211
|
-
*/
|
|
212
|
-
registerAndResolveProject(identity: ProjectIdentity, selector: string): Promise<ProjectRegistrationResult>;
|
|
213
|
-
private performProjectRegistration;
|
|
214
|
-
private scopedProjectRequest;
|
|
188
|
+
resolveWorkspaceProject(agentId: string, workspaceDir?: string): Promise<ProjectIdentity>;
|
|
215
189
|
/**
|
|
216
190
|
* Fetch session context for injection (static session-level context).
|
|
217
191
|
* POST /api/context/inject
|
|
218
192
|
*/
|
|
219
|
-
getContextInject(agentId: string, cwd
|
|
193
|
+
getContextInject(agentId: string, cwd: string | undefined, project: string): Promise<ContextInjectResponse | null>;
|
|
220
194
|
/**
|
|
221
195
|
* Per-turn context search.
|
|
222
196
|
* POST /api/context/search
|
|
@@ -352,9 +326,17 @@ export declare class EngramRestClient {
|
|
|
352
326
|
* Retrieve and decrypt a credential from the vault.
|
|
353
327
|
* GET /api/vault/credentials/{name}
|
|
354
328
|
*/
|
|
355
|
-
getCredential(name: string
|
|
329
|
+
getCredential(name: string, namespace: {
|
|
330
|
+
scope: 'project';
|
|
331
|
+
project: string;
|
|
332
|
+
} | {
|
|
333
|
+
scope: 'global';
|
|
334
|
+
}): Promise<{
|
|
356
335
|
name: string;
|
|
357
336
|
value: string;
|
|
337
|
+
scope: string;
|
|
338
|
+
project_id: string | null;
|
|
339
|
+
id: number;
|
|
358
340
|
} | null>;
|
|
359
341
|
listIssues(params: {
|
|
360
342
|
project?: string;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -8,11 +8,10 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.EngramRestClient = void 0;
|
|
10
10
|
exports.isOutcomeRetirement = isOutcomeRetirement;
|
|
11
|
-
exports.
|
|
11
|
+
exports.resolveProject = resolveProject;
|
|
12
12
|
const node_crypto_1 = require("node:crypto");
|
|
13
13
|
const availability_js_1 = require("./availability.js");
|
|
14
14
|
const identity_js_1 = require("./identity.js");
|
|
15
|
-
const project_identity_v3_js_1 = require("./project-identity-v3.js");
|
|
16
15
|
function isOutcomeRetirement(result) {
|
|
17
16
|
return typeof result !== 'boolean';
|
|
18
17
|
}
|
|
@@ -34,35 +33,17 @@ function parseOutcomeRetirementPayload(text) {
|
|
|
34
33
|
return null;
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
* Register an explicit project override as a selector-only shared scope.
|
|
39
|
-
* Without an override, resolve and register the workspace's full identity.
|
|
40
|
-
*/
|
|
41
|
-
async function resolveAndRegisterProject(client, agentId, workspaceDir, configuredProject) {
|
|
36
|
+
async function resolveProject(client, agentId, workspaceDir, configuredProject) {
|
|
42
37
|
try {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
? { projectId: configuredProject, agentId }
|
|
48
|
-
: (0, identity_js_1.resolveIdentity)(agentId, workspaceDir);
|
|
49
|
-
const selector = clientInstanceId !== undefined ? identity.projectId : configuredProject ?? identity.projectId;
|
|
50
|
-
const registration = await client.registerAndResolveProject(identity, selector);
|
|
51
|
-
if (!registration.ok)
|
|
52
|
-
return registration;
|
|
53
|
-
return {
|
|
54
|
-
...registration,
|
|
55
|
-
projectSelector: selector,
|
|
56
|
-
...(identity.projectIdentityV3 ? { projectIdentityV3: identity.projectIdentityV3 } : {}),
|
|
57
|
-
...(identity.projectIdentityV2 ? { projectIdentityV2: identity.projectIdentityV2 } : {}),
|
|
58
|
-
};
|
|
38
|
+
const project = configuredProject !== undefined
|
|
39
|
+
? (0, identity_js_1.validateProjectID)(configuredProject)
|
|
40
|
+
: (await client.resolveWorkspaceProject(agentId, workspaceDir)).projectId;
|
|
41
|
+
return { ok: true, canonicalProject: project };
|
|
59
42
|
}
|
|
60
43
|
catch (error) {
|
|
61
44
|
const message = error instanceof Error ? error.message : String(error);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const invalid = message.startsWith('PROJECT_IDENTITY_INVALID:');
|
|
65
|
-
return projectRegistrationFailure(invalid ? 'PROJECT_IDENTITY_INVALID' : 'PROJECT_IDENTITY_UNAVAILABLE', message, invalid ? 'regenerate_project_identity_v2' : 'retry_project_identity_registration', invalid ? 400 : 503);
|
|
45
|
+
const code = /^PROJECT_[A-Z_]+$/.test(message) ? message : 'PROJECT_RESOLUTION_UNAVAILABLE';
|
|
46
|
+
return projectResolutionFailure(code, code, 'resolve_current_project_with_go_client', code === 'PROJECT_RESOLUTION_UNAVAILABLE' ? 503 : 400);
|
|
66
47
|
}
|
|
67
48
|
}
|
|
68
49
|
// ---------------------------------------------------------------------------
|
|
@@ -72,172 +53,30 @@ class EngramRestClient {
|
|
|
72
53
|
baseUrl;
|
|
73
54
|
token;
|
|
74
55
|
defaultTimeoutMs;
|
|
75
|
-
completedProjectRegistrations = new Map();
|
|
76
|
-
inFlightProjectRegistrations = new Map();
|
|
77
|
-
v3ContextDescriptors = new Map();
|
|
78
56
|
availability;
|
|
79
|
-
clientInstanceId;
|
|
80
57
|
constructor(config) {
|
|
81
58
|
// Extract origin from potentially path-bearing URL
|
|
82
59
|
this.baseUrl = extractOrigin(config.url);
|
|
83
60
|
this.token = config.token;
|
|
84
61
|
this.defaultTimeoutMs = config.timeoutMs;
|
|
85
62
|
this.availability = new availability_js_1.AvailabilityTracker();
|
|
86
|
-
this.clientInstanceId = config.clientInstanceId;
|
|
87
63
|
}
|
|
88
64
|
// ---------------------------------------------------------------------------
|
|
89
65
|
// Endpoints
|
|
90
66
|
// ---------------------------------------------------------------------------
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
* caller sends its first data request. Concurrent and late calls reuse the
|
|
96
|
-
* same result. Project metadata routes a namespace; the bearer header remains
|
|
97
|
-
* the independent authorization gate.
|
|
98
|
-
*/
|
|
99
|
-
async registerAndResolveProject(identity, selector) {
|
|
100
|
-
const requestedDescriptor = identity.projectIdentityV3;
|
|
101
|
-
let descriptor;
|
|
102
|
-
let validatedIdentity = identity;
|
|
103
|
-
if (requestedDescriptor !== undefined) {
|
|
104
|
-
const validatedDescriptor = validateProjectDescriptorV3(requestedDescriptor);
|
|
105
|
-
if (!validatedDescriptor)
|
|
106
|
-
return projectDescriptorFailure();
|
|
107
|
-
descriptor = validatedDescriptor;
|
|
108
|
-
validatedIdentity = { ...identity, projectIdentityV3: descriptor };
|
|
109
|
-
}
|
|
110
|
-
let validatedSelector = selector;
|
|
111
|
-
if (!descriptor) {
|
|
112
|
-
try {
|
|
113
|
-
validatedSelector = (0, identity_js_1.validateProjectSelectorV2)(selector);
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
return {
|
|
117
|
-
ok: false,
|
|
118
|
-
error: {
|
|
119
|
-
code: 'PROJECT_IDENTITY_INVALID',
|
|
120
|
-
message: 'project selector is empty or malformed',
|
|
121
|
-
upgradeAction: 'regenerate_project_identity_v2',
|
|
122
|
-
httpStatus: 400,
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
const key = JSON.stringify(descriptor ?? [validatedSelector, identity.projectIdentityV2 ?? null]);
|
|
128
|
-
const completed = this.completedProjectRegistrations.get(key);
|
|
129
|
-
if (completed)
|
|
130
|
-
return completed;
|
|
131
|
-
const inFlight = this.inFlightProjectRegistrations.get(key);
|
|
132
|
-
if (inFlight)
|
|
133
|
-
return inFlight;
|
|
134
|
-
const registration = this.performProjectRegistration(validatedIdentity, validatedSelector);
|
|
135
|
-
this.inFlightProjectRegistrations.set(key, registration);
|
|
136
|
-
try {
|
|
137
|
-
const result = await registration;
|
|
138
|
-
if (result.ok && descriptor) {
|
|
139
|
-
this.v3ContextDescriptors.set(selector, descriptor);
|
|
140
|
-
this.v3ContextDescriptors.set(result.canonicalProject, descriptor);
|
|
141
|
-
}
|
|
142
|
-
if (result.ok || result.error.httpStatus === 400 || result.error.httpStatus === 409) {
|
|
143
|
-
this.completedProjectRegistrations.set(key, result);
|
|
144
|
-
}
|
|
145
|
-
return result;
|
|
146
|
-
}
|
|
147
|
-
finally {
|
|
148
|
-
this.inFlightProjectRegistrations.delete(key);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
async performProjectRegistration(identity, selector) {
|
|
152
|
-
if (!this.availability.isAvailable()) {
|
|
153
|
-
return projectRegistrationFailure('PROJECT_IDENTITY_UNAVAILABLE', 'engram is temporarily unavailable', 'retry_project_identity_registration', 503);
|
|
154
|
-
}
|
|
155
|
-
const path = '/api/context/inject';
|
|
156
|
-
const url = this.baseUrl + path;
|
|
157
|
-
const controller = new AbortController();
|
|
158
|
-
const timer = setTimeout(() => controller.abort(), this.defaultTimeoutMs);
|
|
159
|
-
const body = identity.projectIdentityV3
|
|
160
|
-
? {
|
|
161
|
-
project_descriptor: identity.projectIdentityV3,
|
|
162
|
-
identity_only: true,
|
|
163
|
-
}
|
|
164
|
-
: {
|
|
165
|
-
project: selector,
|
|
166
|
-
...(identity.projectIdentityV2 ? { project_identity: identity.projectIdentityV2 } : {}),
|
|
167
|
-
identity_only: true,
|
|
168
|
-
};
|
|
169
|
-
try {
|
|
170
|
-
const response = await fetch(url, {
|
|
171
|
-
method: 'POST',
|
|
172
|
-
headers: {
|
|
173
|
-
'Authorization': `Bearer ${this.token}`,
|
|
174
|
-
'Content-Type': 'application/json',
|
|
175
|
-
'X-Engram-Project-Identity-Adapter': 'openclaw',
|
|
176
|
-
'X-Request-ID': (0, node_crypto_1.randomUUID)(),
|
|
177
|
-
},
|
|
178
|
-
body: JSON.stringify(body),
|
|
179
|
-
signal: controller.signal,
|
|
180
|
-
});
|
|
181
|
-
const text = await response.text();
|
|
182
|
-
let payload = {};
|
|
183
|
-
if (text) {
|
|
184
|
-
try {
|
|
185
|
-
payload = JSON.parse(text);
|
|
186
|
-
}
|
|
187
|
-
catch {
|
|
188
|
-
payload = {};
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
if (!response.ok) {
|
|
192
|
-
if (response.status >= 500 || response.status === 401 || response.status === 403) {
|
|
193
|
-
this.availability.recordFailure();
|
|
194
|
-
}
|
|
195
|
-
const parsed = parseProjectRegistrationError(payload, response.status);
|
|
196
|
-
return projectRegistrationFailure(parsed.code, parsed.message, parsed.upgradeAction, response.status);
|
|
197
|
-
}
|
|
198
|
-
const canonical = readCanonicalProject(payload, identity.projectIdentityV3);
|
|
199
|
-
if (!canonical) {
|
|
200
|
-
this.availability.recordFailure();
|
|
201
|
-
return projectRegistrationFailure('PROJECT_IDENTITY_UNAVAILABLE', 'project identity registration response is malformed', 'retry_project_identity_registration', 503);
|
|
202
|
-
}
|
|
203
|
-
this.availability.recordSuccess();
|
|
204
|
-
return { ok: true, canonicalProject: canonical };
|
|
205
|
-
}
|
|
206
|
-
catch (err) {
|
|
207
|
-
this.availability.recordFailure();
|
|
208
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
209
|
-
return projectRegistrationFailure('PROJECT_IDENTITY_UNAVAILABLE', message, 'retry_project_identity_registration', 503);
|
|
210
|
-
}
|
|
211
|
-
finally {
|
|
212
|
-
clearTimeout(timer);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
scopedProjectRequest(body) {
|
|
216
|
-
if (this.clientInstanceId === undefined)
|
|
217
|
-
return body;
|
|
218
|
-
const descriptor = this.v3ContextDescriptors.get(body.project);
|
|
219
|
-
if (!descriptor)
|
|
220
|
-
return null;
|
|
221
|
-
const { project: _, agent_id: _agentID, ...request } = body;
|
|
222
|
-
return { ...request, project_descriptor: descriptor };
|
|
67
|
+
async resolveWorkspaceProject(agentId, workspaceDir) {
|
|
68
|
+
return (0, identity_js_1.resolveIdentity)(agentId, workspaceDir, {
|
|
69
|
+
env: { ...process.env, ENGRAM_URL: this.baseUrl, ENGRAM_TOKEN: this.token },
|
|
70
|
+
});
|
|
223
71
|
}
|
|
224
72
|
/**
|
|
225
73
|
* Fetch session context for injection (static session-level context).
|
|
226
74
|
* POST /api/context/inject
|
|
227
75
|
*/
|
|
228
|
-
async getContextInject(agentId, cwd, project
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
return null;
|
|
233
|
-
return this.post('/api/context/inject', projectDescriptor
|
|
234
|
-
? { project_descriptor: projectDescriptor }
|
|
235
|
-
: {
|
|
236
|
-
agent_id: agentId,
|
|
237
|
-
...(cwd ? { cwd } : {}),
|
|
238
|
-
...(project ? { project } : {}),
|
|
239
|
-
...(projectIdentityV2 ? { project_identity: projectIdentityV2 } : {}),
|
|
240
|
-
}, 15_000);
|
|
76
|
+
async getContextInject(agentId, cwd, project) {
|
|
77
|
+
return this.post('/api/context/inject', {
|
|
78
|
+
agent_id: agentId, ...(cwd ? { cwd } : {}), project,
|
|
79
|
+
}, 15_000);
|
|
241
80
|
}
|
|
242
81
|
/**
|
|
243
82
|
* Per-turn context search.
|
|
@@ -245,8 +84,7 @@ class EngramRestClient {
|
|
|
245
84
|
*/
|
|
246
85
|
async searchContext(body) {
|
|
247
86
|
// Context search does vector query (embedding + pgvector) — needs more than default 5s.
|
|
248
|
-
|
|
249
|
-
return request ? this.post('/api/context/search', request, 15_000) : null;
|
|
87
|
+
return this.post('/api/context/search', body, 15_000);
|
|
250
88
|
}
|
|
251
89
|
/**
|
|
252
90
|
* Search for relevant decisions.
|
|
@@ -315,8 +153,6 @@ class EngramRestClient {
|
|
|
315
153
|
* synthetic one per call, preventing phantom session proliferation.
|
|
316
154
|
*/
|
|
317
155
|
async bulkImport(observations, sessionId) {
|
|
318
|
-
if (this.clientInstanceId !== undefined)
|
|
319
|
-
return null;
|
|
320
156
|
if (observations.length === 0)
|
|
321
157
|
return { imported: 0, skipped_duplicates: 0 };
|
|
322
158
|
// All observations in a batch must share the same project.
|
|
@@ -466,8 +302,7 @@ class EngramRestClient {
|
|
|
466
302
|
body.anchor_id = params.anchor_id;
|
|
467
303
|
if (params?.limit)
|
|
468
304
|
body.limit = params.limit;
|
|
469
|
-
const
|
|
470
|
-
const resp = request ? await this.post('/api/context/search', request, 15_000) : null;
|
|
305
|
+
const resp = await this.post('/api/context/search', body, 15_000);
|
|
471
306
|
return resp?.observations ?? [];
|
|
472
307
|
}
|
|
473
308
|
/**
|
|
@@ -487,8 +322,11 @@ class EngramRestClient {
|
|
|
487
322
|
* Retrieve and decrypt a credential from the vault.
|
|
488
323
|
* GET /api/vault/credentials/{name}
|
|
489
324
|
*/
|
|
490
|
-
async getCredential(name) {
|
|
491
|
-
|
|
325
|
+
async getCredential(name, namespace) {
|
|
326
|
+
const query = new URLSearchParams({ scope: namespace.scope });
|
|
327
|
+
if (namespace.scope === 'project')
|
|
328
|
+
query.set('project', namespace.project);
|
|
329
|
+
return this.get(`/api/vault/credentials/${encodeURIComponent(name)}?${query}`);
|
|
492
330
|
}
|
|
493
331
|
// ---------------------------------------------------------------------------
|
|
494
332
|
// Issues — cross-project agent issue tracking
|
|
@@ -595,125 +433,7 @@ function extractOrigin(rawUrl) {
|
|
|
595
433
|
return trimmed.replace(/\/$/, '');
|
|
596
434
|
}
|
|
597
435
|
}
|
|
598
|
-
function
|
|
436
|
+
function projectResolutionFailure(code, message, upgradeAction, httpStatus) {
|
|
599
437
|
return { ok: false, error: { code, message, upgradeAction, httpStatus } };
|
|
600
438
|
}
|
|
601
|
-
function projectDescriptorFailure() {
|
|
602
|
-
return projectRegistrationFailure('PROJECT_DESCRIPTOR_INVALID', 'project descriptor is invalid', 'repair_project_descriptor', 400);
|
|
603
|
-
}
|
|
604
|
-
const V3_DESCRIPTOR_FIELDS = {
|
|
605
|
-
version: true,
|
|
606
|
-
anchor_project_id: true,
|
|
607
|
-
name: true,
|
|
608
|
-
scope: true,
|
|
609
|
-
normalized_git_remotes: true,
|
|
610
|
-
legacy_identifiers: true,
|
|
611
|
-
client_instance_id: true,
|
|
612
|
-
};
|
|
613
|
-
const V3_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
614
|
-
const V3_PROJECT_RESOLUTION_FIELDS = {
|
|
615
|
-
outcome: true,
|
|
616
|
-
project_key: true,
|
|
617
|
-
resolved_scope: true,
|
|
618
|
-
correlation: true,
|
|
619
|
-
redirect_reference: true,
|
|
620
|
-
};
|
|
621
|
-
function isValidOpaqueReferenceV3(value) {
|
|
622
|
-
return typeof value === 'string' &&
|
|
623
|
-
value.length > 0 &&
|
|
624
|
-
Array.from(value).length <= 256 &&
|
|
625
|
-
!/[\p{White_Space}\p{Cc}\/\\@]/u.test(value);
|
|
626
|
-
}
|
|
627
|
-
function validateProjectDescriptorV3(descriptor) {
|
|
628
|
-
try {
|
|
629
|
-
if (typeof descriptor !== 'object' || descriptor === null || Array.isArray(descriptor))
|
|
630
|
-
return null;
|
|
631
|
-
const keys = Object.keys(descriptor);
|
|
632
|
-
if (keys.length !== 7 || keys.some((key) => !Object.hasOwn(V3_DESCRIPTOR_FIELDS, key)))
|
|
633
|
-
return null;
|
|
634
|
-
if (!('version' in descriptor) ||
|
|
635
|
-
!('anchor_project_id' in descriptor) ||
|
|
636
|
-
!('name' in descriptor) ||
|
|
637
|
-
!('scope' in descriptor) ||
|
|
638
|
-
!('normalized_git_remotes' in descriptor) ||
|
|
639
|
-
!('legacy_identifiers' in descriptor) ||
|
|
640
|
-
!('client_instance_id' in descriptor))
|
|
641
|
-
return null;
|
|
642
|
-
return (0, project_identity_v3_js_1.buildProjectIdentityV3)({
|
|
643
|
-
anchor: {
|
|
644
|
-
version: descriptor.version,
|
|
645
|
-
project_id: descriptor.anchor_project_id,
|
|
646
|
-
name: descriptor.name,
|
|
647
|
-
scope: descriptor.scope,
|
|
648
|
-
},
|
|
649
|
-
version: descriptor.version,
|
|
650
|
-
anchor_project_id: descriptor.anchor_project_id,
|
|
651
|
-
name: descriptor.name,
|
|
652
|
-
scope: descriptor.scope,
|
|
653
|
-
normalized_git_remotes: descriptor.normalized_git_remotes,
|
|
654
|
-
legacy_identifiers: descriptor.legacy_identifiers,
|
|
655
|
-
client_instance_id: descriptor.client_instance_id,
|
|
656
|
-
});
|
|
657
|
-
}
|
|
658
|
-
catch {
|
|
659
|
-
return null;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
function readCanonicalProject(payload, descriptor) {
|
|
663
|
-
if (!payload || typeof payload !== 'object')
|
|
664
|
-
return '';
|
|
665
|
-
if (descriptor) {
|
|
666
|
-
if (!Object.hasOwn(payload, 'project_resolution_v3') || !('project_resolution_v3' in payload))
|
|
667
|
-
return '';
|
|
668
|
-
const resolution = payload.project_resolution_v3;
|
|
669
|
-
if (!resolution || typeof resolution !== 'object' || Array.isArray(resolution))
|
|
670
|
-
return '';
|
|
671
|
-
const typedResolution = resolution;
|
|
672
|
-
const keys = Object.keys(typedResolution);
|
|
673
|
-
if (keys.some((key) => !Object.hasOwn(V3_PROJECT_RESOLUTION_FIELDS, key)) ||
|
|
674
|
-
!Object.hasOwn(typedResolution, 'outcome') ||
|
|
675
|
-
!Object.hasOwn(typedResolution, 'project_key') ||
|
|
676
|
-
!Object.hasOwn(typedResolution, 'resolved_scope') ||
|
|
677
|
-
!Object.hasOwn(typedResolution, 'correlation'))
|
|
678
|
-
return '';
|
|
679
|
-
const { outcome, project_key, resolved_scope, correlation, redirect_reference: redirectReference } = typedResolution;
|
|
680
|
-
if ((outcome !== 'PROJECT_RESOLVED' && outcome !== 'PROJECT_REDIRECTED') ||
|
|
681
|
-
keys.length !== (outcome === 'PROJECT_REDIRECTED' ? 5 : 4) ||
|
|
682
|
-
typeof project_key !== 'string' ||
|
|
683
|
-
!V3_UUID.test(project_key) ||
|
|
684
|
-
resolved_scope !== descriptor.scope ||
|
|
685
|
-
!isValidOpaqueReferenceV3(correlation) ||
|
|
686
|
-
(outcome === 'PROJECT_REDIRECTED' && !isValidOpaqueReferenceV3(redirectReference)))
|
|
687
|
-
return '';
|
|
688
|
-
return project_key;
|
|
689
|
-
}
|
|
690
|
-
if (!('canonical_project' in payload))
|
|
691
|
-
return '';
|
|
692
|
-
try {
|
|
693
|
-
return (0, identity_js_1.validateCanonicalProjectV2)(payload.canonical_project);
|
|
694
|
-
}
|
|
695
|
-
catch {
|
|
696
|
-
return '';
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
function parseProjectRegistrationError(payload, status) {
|
|
700
|
-
const fallback = status === 400
|
|
701
|
-
? { code: 'PROJECT_IDENTITY_INVALID', upgradeAction: 'regenerate_project_identity_v2' }
|
|
702
|
-
: status === 409
|
|
703
|
-
? { code: 'PROJECT_IDENTITY_AMBIGUOUS', upgradeAction: 'send_project_identity_v2' }
|
|
704
|
-
: { code: 'PROJECT_IDENTITY_UNAVAILABLE', upgradeAction: 'retry_project_identity_registration' };
|
|
705
|
-
if (!payload || typeof payload !== 'object') {
|
|
706
|
-
return { ...fallback, message: `HTTP ${status} project identity registration failed` };
|
|
707
|
-
}
|
|
708
|
-
const error = payload.error;
|
|
709
|
-
if (!error || typeof error !== 'object') {
|
|
710
|
-
return { ...fallback, message: `HTTP ${status} project identity registration failed` };
|
|
711
|
-
}
|
|
712
|
-
const typed = error;
|
|
713
|
-
return {
|
|
714
|
-
code: typeof typed.code === 'string' ? typed.code : fallback.code,
|
|
715
|
-
message: typeof typed.message === 'string' ? typed.message : `HTTP ${status} project identity registration failed`,
|
|
716
|
-
upgradeAction: typeof typed.upgrade_action === 'string' ? typed.upgrade_action : fallback.upgradeAction,
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
439
|
//# sourceMappingURL=client.js.map
|