fuli-context 0.7.4-beta.3 → 0.7.6
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 +77 -6
- package/README.zh-CN.md +69 -6
- package/compose.graphiti.yml +6 -6
- package/dist/web/assets/AboutPage-sLV9WChi.js +1 -0
- package/dist/web/assets/ConnectionsPage-BWn4ywGJ.js +1 -0
- package/dist/web/assets/KnowledgeEditDialog-CZ5ziPrD.js +1 -0
- package/dist/web/assets/KnowledgeInspector-CRQWOaos.js +1 -0
- package/dist/web/assets/KnowledgeOrganizerPage-Dfj3vIpU.js +1 -0
- package/dist/web/assets/KnowledgePage-BRYC9S5Y.js +1 -0
- package/dist/web/assets/KnowledgeWorkspace-ChEB5Bwk.js +4 -0
- package/dist/web/assets/OverviewPage-Cd66M0RT.js +1 -0
- package/dist/web/assets/PersonalProfilePage-RCFHL0Wz.js +1 -0
- package/dist/web/assets/PersonalProjectsPage-DEh8XWby.js +1 -0
- package/dist/web/assets/ProjectAgentsPage-Crh7PrXa.css +1 -0
- package/dist/web/assets/ProjectAgentsPage-DPnaH-TR.js +11 -0
- package/dist/web/assets/PublicProjectsPage-mstPEjHe.js +1 -0
- package/dist/web/assets/ReviewPage-6Y1SmfZy.js +1 -0
- package/dist/web/assets/SearchableSelect-D3HM8YF8.js +1 -0
- package/dist/web/assets/SettingsPage--LdTMUm7.js +1 -0
- package/dist/web/assets/SettingsPage-CwZp2ka4.css +1 -0
- package/dist/web/assets/WritingTastePage-CIpKswvs.js +1 -0
- package/dist/web/assets/{console-D_2zC4lm.js → console-BT1P2Db4.js} +1 -1
- package/dist/web/assets/{conversation-launcher-settings-DQmMH2j7.js → conversation-launcher-settings-DrJEotdf.js} +1 -1
- package/dist/web/assets/i18n-js6gfc7j.js +9 -0
- package/dist/web/assets/{identity-DmGcY3Y6.js → identity-CfDfanpa.js} +1 -1
- package/dist/web/assets/index-BnH5mcZx.css +1 -0
- package/dist/web/assets/index-GqJf1xqg.js +2 -0
- package/dist/web/assets/{model-CVoOdRsL.js → model-DJkLAJsg.js} +1 -1
- package/dist/web/assets/{useApi-CROJJdhE-CBNg4CdH.js → useApi-CROJJdhE-BdSti7Y2.js} +1 -1
- package/dist/web/assets/vue-router-Kk67EaCP.js +1 -0
- package/dist/web/index.html +6 -6
- package/graph-provider/fuli_graph/app.py +8 -0
- package/graph-provider/fuli_graph/collaboration_context.py +69 -6
- package/graph-provider/fuli_graph/knowledge_search.py +84 -5
- package/graph-provider/fuli_graph/model_validation.py +130 -0
- package/graph-provider/fuli_graph/models.py +24 -5
- package/graph-provider/fuli_graph/project_agent_access.py +54 -0
- package/graph-provider/fuli_graph/project_agent_coordination_models.py +22 -0
- package/graph-provider/fuli_graph/project_agent_executor_models.py +635 -0
- package/graph-provider/fuli_graph/project_agent_models.py +278 -0
- package/graph-provider/fuli_graph/project_agent_routes.py +626 -0
- package/graph-provider/fuli_graph/project_agent_task_models.py +545 -0
- package/graph-provider/fuli_graph/runtime.py +259 -0
- package/graph-provider/fuli_graph/search_projection.py +3 -0
- package/graph-provider/fuli_graph/store.py +6 -0
- package/graph-provider/fuli_graph/store_knowledge.py +62 -9
- package/graph-provider/fuli_graph/store_project_agent_coordination_policy.py +122 -0
- package/graph-provider/fuli_graph/store_project_agent_executor_learning.py +756 -0
- package/graph-provider/fuli_graph/store_project_agent_executor_routing.py +601 -0
- package/graph-provider/fuli_graph/store_project_agent_executors.py +1087 -0
- package/graph-provider/fuli_graph/store_project_agent_task_reads.py +458 -0
- package/graph-provider/fuli_graph/store_project_agent_task_recruitment.py +705 -0
- package/graph-provider/fuli_graph/store_project_agent_task_staffing.py +586 -0
- package/graph-provider/fuli_graph/store_project_agent_tasks.py +1151 -0
- package/graph-provider/fuli_graph/store_project_agents.py +965 -0
- package/graph-provider/pyproject.toml +2 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/capturing-session-knowledge/SKILL.md +39 -0
- package/src/adaptive-runtime/executor-pool.js +127 -0
- package/src/adaptive-runtime/graph-services.js +166 -0
- package/src/adaptive-runtime/lease-client.js +335 -0
- package/src/adaptive-runtime/runtime-broker.js +318 -0
- package/src/adaptive-runtime/settings.js +111 -0
- package/src/adaptive-runtime/state.js +74 -0
- package/src/agent-tools/graph-definitions.js +419 -0
- package/src/agent-tools/graph-handlers.js +65 -0
- package/src/agent-tools/project-agent-definitions.js +307 -0
- package/src/backup/graph-backup.js +289 -0
- package/src/backup/identity-reconciliation.js +208 -0
- package/src/backup/runtime-adapters.js +269 -0
- package/src/cli/command-registry.js +6 -2
- package/src/cli/graph-data-command.js +112 -0
- package/src/cli/local-runtime-command.js +16 -2
- package/src/cli/setup-command.js +19 -3
- package/src/cli/update-command.js +4 -0
- package/src/cli.js +6 -0
- package/src/graphiti/collaboration-preference-projection.js +29 -1
- package/src/graphiti/collaboration-preference-workflow.js +121 -0
- package/src/graphiti/federated-application.js +53 -90
- package/src/graphiti/project-agent-control-plane.js +275 -0
- package/src/graphiti/project-agent-mapping.js +1024 -0
- package/src/graphiti/project-agent-workflows.js +576 -0
- package/src/graphiti/provider-client.js +282 -1
- package/src/http/api-router.js +63 -9
- package/src/http/graph-api-router.js +290 -0
- package/src/local-runtime/lifecycle.js +46 -10
- package/src/mcp/context-resources.js +15 -6
- package/src/mcp/create-mcp-server.js +51 -16
- package/src/mcp/instructions.js +7 -5
- package/src/mcp/runtime.js +17 -5
- package/src/mcp/session-id.js +38 -1
- package/src/mcp/tool-annotations.js +71 -0
- package/src/mcp-server.js +23 -6
- package/src/native-runtime/runtime.js +717 -0
- package/src/server.js +6 -2
- package/src/setup/agent-installation-status.js +7 -1
- package/src/setup/agents.js +3 -1
- package/src/setup/claude-code-config.js +3 -1
- package/src/setup/codex-bootstrap.js +11 -10
- package/src/setup/codex-config.js +7 -1
- package/src/setup/cursor-config.js +3 -1
- package/src/setup/graph-runtime.js +158 -13
- package/src/setup/neo4j-memory-profile.js +43 -0
- package/src/setup/options.js +38 -2
- package/src/setup/paths.js +14 -0
- package/src/setup/setup.js +37 -1
- package/src/system/resource-monitor.js +181 -16
- package/src/system/runtime-settings.js +10 -1
- package/src/system/system-service.js +27 -2
- package/dist/web/assets/AboutPage-Dpf5fRWv.js +0 -1
- package/dist/web/assets/ConnectionsPage-D21aUDCP.js +0 -1
- package/dist/web/assets/KnowledgeEditDialog-u7lpfN3j.js +0 -1
- package/dist/web/assets/KnowledgeInspector-k4xnHtXd.js +0 -1
- package/dist/web/assets/KnowledgeOrganizerPage-Bdj7Rn84.js +0 -1
- package/dist/web/assets/KnowledgePage-UHVAbC1W.js +0 -1
- package/dist/web/assets/KnowledgeWorkspace-Lq3d-MeC.js +0 -4
- package/dist/web/assets/OverviewPage-CycAgA1V.js +0 -1
- package/dist/web/assets/PersonalProfilePage-U9oIV5FT.js +0 -1
- package/dist/web/assets/PersonalProjectsPage-C5RpXKcA.js +0 -1
- package/dist/web/assets/PublicProjectsPage-DiWxm35E.js +0 -1
- package/dist/web/assets/ReviewPage-jxRfGSJK.js +0 -1
- package/dist/web/assets/SearchableSelect-B3-5IPup.js +0 -1
- package/dist/web/assets/SettingsPage-BqfGDOho.js +0 -1
- package/dist/web/assets/SettingsPage-CAfz4qiV.css +0 -1
- package/dist/web/assets/WritingTastePage-BJxhMqJR.js +0 -1
- package/dist/web/assets/i18n-CwqXDI1C.js +0 -5
- package/dist/web/assets/index-IUGLt4lG.js +0 -2
- package/dist/web/assets/index-X2j29j8i.css +0 -1
- package/dist/web/assets/vue-router-CWSsUUio.js +0 -1
|
@@ -79,6 +79,281 @@ export class GraphitiProviderClient {
|
|
|
79
79
|
`/v1/personal-projects/${encodeURIComponent(projectId)}?${query}`
|
|
80
80
|
);
|
|
81
81
|
}
|
|
82
|
+
upsertProjectAgent(input) {
|
|
83
|
+
return this.#request('/v1/project-agents', { method: 'PUT', body: input });
|
|
84
|
+
}
|
|
85
|
+
listProjectAgents(
|
|
86
|
+
personalSpaceId,
|
|
87
|
+
personalProjectId = null,
|
|
88
|
+
{ status = null, capability = null } = {}
|
|
89
|
+
) {
|
|
90
|
+
const query = new URLSearchParams({
|
|
91
|
+
personal_space_id: personalSpaceId
|
|
92
|
+
});
|
|
93
|
+
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
94
|
+
if (status) query.set('status', status);
|
|
95
|
+
if (capability) query.set('capability', capability);
|
|
96
|
+
return this.#request(`/v1/project-agents?${query}`);
|
|
97
|
+
}
|
|
98
|
+
getProjectAgent(personalSpaceId, personalProjectId, agentId) {
|
|
99
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
100
|
+
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
101
|
+
return this.#request(
|
|
102
|
+
`/v1/project-agents/${encodeURIComponent(agentId)}?${query}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
deleteProjectAgent(personalSpaceId, agentId, reason = 'archived by user') {
|
|
106
|
+
const query = new URLSearchParams({
|
|
107
|
+
personal_space_id: personalSpaceId,
|
|
108
|
+
reason
|
|
109
|
+
});
|
|
110
|
+
return this.#request(
|
|
111
|
+
`/v1/project-agents/${encodeURIComponent(agentId)}?${query}`,
|
|
112
|
+
{ method: 'DELETE' }
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
cleanupProjectAgentTestRoles(personalSpaceId, testSource) {
|
|
116
|
+
const query = new URLSearchParams({
|
|
117
|
+
personal_space_id: personalSpaceId,
|
|
118
|
+
test_source: testSource
|
|
119
|
+
});
|
|
120
|
+
return this.#request(`/v1/project-agents/test-cleanup?${query}`, {
|
|
121
|
+
method: 'POST'
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
createProjectAgentAssignment(input) {
|
|
125
|
+
return this.#request('/v1/project-agent-assignments', {
|
|
126
|
+
method: 'POST', body: input
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
listProjectAgentAssignments({
|
|
130
|
+
personalSpaceId,
|
|
131
|
+
personalProjectId = null,
|
|
132
|
+
agentId = null,
|
|
133
|
+
status = null
|
|
134
|
+
}) {
|
|
135
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
136
|
+
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
137
|
+
if (agentId) query.set('agent_id', agentId);
|
|
138
|
+
if (status) query.set('status', status);
|
|
139
|
+
return this.#request(`/v1/project-agent-assignments?${query}`);
|
|
140
|
+
}
|
|
141
|
+
endProjectAgentAssignment(input) {
|
|
142
|
+
return this.#request('/v1/project-agent-assignments/end', {
|
|
143
|
+
method: 'POST', body: input
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
replaceProjectAgentAssignment(input) {
|
|
147
|
+
return this.#request('/v1/project-agent-assignments/replace', {
|
|
148
|
+
method: 'POST', body: input
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
submitProjectAgentTask(input) {
|
|
152
|
+
return this.#request('/v1/project-agent-tasks', {
|
|
153
|
+
method: 'POST', body: input
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
listProjectAgentTasks({
|
|
157
|
+
personalSpaceId,
|
|
158
|
+
personalProjectId = null,
|
|
159
|
+
agentId = null,
|
|
160
|
+
status = null,
|
|
161
|
+
limit = null
|
|
162
|
+
}) {
|
|
163
|
+
const query = new URLSearchParams({
|
|
164
|
+
personal_space_id: personalSpaceId
|
|
165
|
+
});
|
|
166
|
+
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
167
|
+
if (agentId) query.set('agent_id', agentId);
|
|
168
|
+
if (status) query.set('status', status);
|
|
169
|
+
if (limit !== null && limit !== undefined) query.set('limit', String(limit));
|
|
170
|
+
return this.#request(`/v1/project-agent-tasks?${query}`);
|
|
171
|
+
}
|
|
172
|
+
viewProjectAgentTask(personalSpaceId, taskId, { includeEvents = true } = {}) {
|
|
173
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
174
|
+
query.set('include_events', String(includeEvents));
|
|
175
|
+
return this.#request(
|
|
176
|
+
`/v1/project-agent-tasks/${encodeURIComponent(taskId)}?${query}`
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
recordProjectAgentTaskActivity(input) {
|
|
180
|
+
return this.#request(
|
|
181
|
+
`/v1/project-agent-tasks/${encodeURIComponent(input.task_id ?? input.taskId)}/events`,
|
|
182
|
+
{
|
|
183
|
+
method: 'POST', body: input
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
listProjectAgentActivity({
|
|
188
|
+
personalSpaceId,
|
|
189
|
+
agentId,
|
|
190
|
+
fromDate = null,
|
|
191
|
+
toDate = null
|
|
192
|
+
}) {
|
|
193
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
194
|
+
const query = new URLSearchParams({
|
|
195
|
+
personal_space_id: personalSpaceId,
|
|
196
|
+
from: fromDate ?? toDate ?? today,
|
|
197
|
+
to: toDate ?? fromDate ?? today
|
|
198
|
+
});
|
|
199
|
+
return this.#request(
|
|
200
|
+
`/v1/project-agents/${encodeURIComponent(agentId)}/activity?${query}`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
getProjectAgentCoordinationPolicy(personalSpaceId, personalProjectId) {
|
|
204
|
+
const query = new URLSearchParams({
|
|
205
|
+
personal_space_id: personalSpaceId,
|
|
206
|
+
personal_project_id: personalProjectId
|
|
207
|
+
});
|
|
208
|
+
return this.#request(`/v1/project-agent-coordination-policy?${query}`);
|
|
209
|
+
}
|
|
210
|
+
updateProjectAgentCoordinationPolicy(input) {
|
|
211
|
+
return this.#request('/v1/project-agent-coordination-policy', {
|
|
212
|
+
method: 'PUT', body: input
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
getProjectAgentRecruitmentPolicy(personalSpaceId) {
|
|
216
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
217
|
+
return this.#request(`/v1/project-agent-recruitment-policy?${query}`);
|
|
218
|
+
}
|
|
219
|
+
updateProjectAgentRecruitmentPolicy(input) {
|
|
220
|
+
return this.#request('/v1/project-agent-recruitment-policy', {
|
|
221
|
+
method: 'PUT', body: input
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
listProjectAgentRecruitments({
|
|
225
|
+
personalSpaceId,
|
|
226
|
+
personalProjectId = null,
|
|
227
|
+
taskId = null,
|
|
228
|
+
status = null
|
|
229
|
+
}) {
|
|
230
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
231
|
+
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
232
|
+
if (taskId) query.set('task_id', taskId);
|
|
233
|
+
if (status) query.set('status', status);
|
|
234
|
+
return this.#request(`/v1/project-agent-recruitments?${query}`);
|
|
235
|
+
}
|
|
236
|
+
decideProjectAgentRecruitment(input) {
|
|
237
|
+
return this.#request(
|
|
238
|
+
`/v1/project-agent-recruitments/${encodeURIComponent(
|
|
239
|
+
input.recruitment_id ?? input.recruitmentId
|
|
240
|
+
)}/decision`,
|
|
241
|
+
{ method: 'POST', body: input }
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
upsertExecutor(input) {
|
|
245
|
+
return this.#request('/v1/executors', { method: 'PUT', body: input });
|
|
246
|
+
}
|
|
247
|
+
listExecutors(
|
|
248
|
+
personalSpaceId,
|
|
249
|
+
{ capability = null, availableOnly = false } = {}
|
|
250
|
+
) {
|
|
251
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
252
|
+
if (capability) query.set('capability', capability);
|
|
253
|
+
if (availableOnly) query.set('available_only', 'true');
|
|
254
|
+
return this.#request(`/v1/executors?${query}`);
|
|
255
|
+
}
|
|
256
|
+
getExecutor(personalSpaceId, executorId) {
|
|
257
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
258
|
+
return this.#request(`/v1/executors/${encodeURIComponent(executorId)}?${query}`);
|
|
259
|
+
}
|
|
260
|
+
deleteExecutor(personalSpaceId, executorId) {
|
|
261
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
262
|
+
return this.#request(`/v1/executors/${encodeURIComponent(executorId)}?${query}`, {
|
|
263
|
+
method: 'DELETE'
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
preflightExecutor(input) {
|
|
267
|
+
return this.#request('/v1/executors/preflight', { method: 'POST', body: input });
|
|
268
|
+
}
|
|
269
|
+
authorizeExecutor(input) {
|
|
270
|
+
return this.#request('/v1/executors/authorization', {
|
|
271
|
+
method: 'POST', body: input
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
reportExecutorHealth(input) {
|
|
275
|
+
return this.#request('/v1/executors/health', {
|
|
276
|
+
method: 'POST', body: input
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
recordProjectAgentExecutorActual(input) {
|
|
280
|
+
return this.#request('/v1/project-agent-executor-actuals', {
|
|
281
|
+
method: 'POST', body: input
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
upsertExecutorRoutingRule(input) {
|
|
285
|
+
return this.#request('/v1/executor-routing-rules', {
|
|
286
|
+
method: 'PUT', body: input
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
updateExecutorRoutingRule(input) {
|
|
290
|
+
return this.#request(
|
|
291
|
+
`/v1/executor-routing-rules/${encodeURIComponent(
|
|
292
|
+
input.rule_id ?? input.ruleId
|
|
293
|
+
)}`,
|
|
294
|
+
{ method: 'PATCH', body: input }
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
listExecutorRoutingRules({
|
|
298
|
+
personalSpaceId,
|
|
299
|
+
scope = null,
|
|
300
|
+
personalProjectId = null,
|
|
301
|
+
taskId = null,
|
|
302
|
+
status = null,
|
|
303
|
+
enabled = null
|
|
304
|
+
}) {
|
|
305
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
306
|
+
if (scope) query.set('scope', scope);
|
|
307
|
+
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
308
|
+
if (taskId) query.set('task_id', taskId);
|
|
309
|
+
if (status) query.set('status', status);
|
|
310
|
+
else if (enabled !== null && enabled !== undefined) {
|
|
311
|
+
query.set('status', enabled ? 'active' : 'disabled');
|
|
312
|
+
}
|
|
313
|
+
return this.#request(`/v1/executor-routing-rules?${query}`);
|
|
314
|
+
}
|
|
315
|
+
getExecutorRoutingRule(personalSpaceId, ruleId) {
|
|
316
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
317
|
+
return this.#request(
|
|
318
|
+
`/v1/executor-routing-rules/${encodeURIComponent(ruleId)}?${query}`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
deleteExecutorRoutingRule(personalSpaceId, ruleId) {
|
|
322
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
323
|
+
return this.#request(
|
|
324
|
+
`/v1/executor-routing-rules/${encodeURIComponent(ruleId)}?${query}`,
|
|
325
|
+
{ method: 'DELETE' }
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
recordProjectAgentTaskOutcome(input) {
|
|
329
|
+
return this.#request('/v1/project-agent-routing-outcomes', {
|
|
330
|
+
method: 'POST', body: input
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
listProjectAgentRoutingLearning({
|
|
334
|
+
personalSpaceId,
|
|
335
|
+
personalProjectId = null,
|
|
336
|
+
workKind = null,
|
|
337
|
+
agentId = null,
|
|
338
|
+
executorId = null
|
|
339
|
+
}) {
|
|
340
|
+
const query = new URLSearchParams({ personal_space_id: personalSpaceId });
|
|
341
|
+
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
342
|
+
if (workKind) query.set('work_kind', workKind);
|
|
343
|
+
if (agentId) query.set('agent_id', agentId);
|
|
344
|
+
if (executorId) query.set('executor_id', executorId);
|
|
345
|
+
return this.#request(`/v1/project-agent-routing-learning?${query}`);
|
|
346
|
+
}
|
|
347
|
+
ignoreProjectAgentRoutingLearning(input) {
|
|
348
|
+
return this.#request('/v1/project-agent-routing-learning/ignore', {
|
|
349
|
+
method: 'POST', body: input
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
resetProjectAgentRoutingLearning(input) {
|
|
353
|
+
return this.#request('/v1/project-agent-routing-learning/reset', {
|
|
354
|
+
method: 'POST', body: input
|
|
355
|
+
});
|
|
356
|
+
}
|
|
82
357
|
createPublicationDraft(input) {
|
|
83
358
|
return this.#request('/v1/publication-drafts', { method: 'POST', body: input });
|
|
84
359
|
}
|
|
@@ -320,12 +595,18 @@ export class GraphitiProviderClient {
|
|
|
320
595
|
);
|
|
321
596
|
}
|
|
322
597
|
search(input) { return this.#request('/v1/search', { method: 'POST', body: input }); }
|
|
323
|
-
collaborationPreferences(
|
|
598
|
+
collaborationPreferences(
|
|
599
|
+
personalSpaceId,
|
|
600
|
+
personalProjectId = null,
|
|
601
|
+
limit = 100,
|
|
602
|
+
projectAgentId = null
|
|
603
|
+
) {
|
|
324
604
|
const query = new URLSearchParams({
|
|
325
605
|
personal_space_id: personalSpaceId,
|
|
326
606
|
limit: String(limit)
|
|
327
607
|
});
|
|
328
608
|
if (personalProjectId) query.set('personal_project_id', personalProjectId);
|
|
609
|
+
if (projectAgentId) query.set('project_agent_id', projectAgentId);
|
|
329
610
|
return this.#request(`/v1/collaboration-preferences?${query}`);
|
|
330
611
|
}
|
|
331
612
|
graph(spaceId, limit = 500, personalProjectId = null, offset = null) {
|
package/src/http/api-router.js
CHANGED
|
@@ -36,13 +36,67 @@ export async function handleApiRequest({
|
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
if (system && url.pathname === '/api/system/runtime' && request.method === 'GET') {
|
|
40
|
+
sendJson(response, 200, system.runtimeStatus());
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (system && url.pathname === '/api/system/runtime/leases' && request.method === 'POST') {
|
|
45
|
+
sendJson(response, 201, await system.acquireRuntimeLease(await readJson(request)));
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const runtimeLease = url.pathname.match(/^\/api\/system\/runtime\/leases\/([^/]+)$/);
|
|
50
|
+
if (system && runtimeLease && request.method === 'PATCH') {
|
|
51
|
+
sendJson(
|
|
52
|
+
response,
|
|
53
|
+
200,
|
|
54
|
+
system.refreshRuntimeLease(decodeURIComponent(runtimeLease[1]))
|
|
55
|
+
);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (system && runtimeLease && request.method === 'DELETE') {
|
|
59
|
+
sendJson(
|
|
60
|
+
response,
|
|
61
|
+
200,
|
|
62
|
+
system.releaseRuntimeLease(decodeURIComponent(runtimeLease[1]))
|
|
63
|
+
);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const externalRequest = () => handleExternalKnowledgeApiRequest({
|
|
68
|
+
request, response, url, externalKnowledge, connectedKnowledge
|
|
69
|
+
});
|
|
70
|
+
const handledExternal = system?.withGraphRuntimeLease &&
|
|
71
|
+
externalRequestNeedsGraph(url.pathname, request.method)
|
|
72
|
+
? await system.withGraphRuntimeLease(
|
|
73
|
+
`http:${request.method}:${url.pathname}`,
|
|
74
|
+
externalRequest
|
|
75
|
+
)
|
|
76
|
+
: await externalRequest();
|
|
77
|
+
if (handledExternal) return true;
|
|
78
|
+
|
|
79
|
+
const graphRequest = () => handleGraphApiRequest({ request, response, url, app });
|
|
80
|
+
if (system?.withGraphRuntimeLease && url.pathname.startsWith('/api/')) {
|
|
81
|
+
return system.withGraphRuntimeLease(
|
|
82
|
+
`http:${request.method}:${url.pathname}`,
|
|
83
|
+
graphRequest
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return graphRequest();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function externalRequestNeedsGraph(pathname, method) {
|
|
90
|
+
if (pathname === '/api/connected-knowledge/search' && method === 'POST') return true;
|
|
91
|
+
if (pathname === '/api/external-knowledge/bindings' && method === 'POST') return true;
|
|
92
|
+
if (
|
|
93
|
+
/^\/api\/external-knowledge\/bindings\/[^/]+\/sync$/.test(pathname) &&
|
|
94
|
+
method === 'POST'
|
|
95
|
+
) return true;
|
|
96
|
+
if (
|
|
97
|
+
/^\/api\/external-knowledge\/bindings\/[^/]+\/targets$/.test(pathname) &&
|
|
98
|
+
method === 'PATCH'
|
|
99
|
+
) return true;
|
|
100
|
+
return /^\/api\/external-knowledge\/bindings\/[^/]+$/.test(pathname) &&
|
|
101
|
+
method === 'DELETE';
|
|
48
102
|
}
|
|
@@ -178,6 +178,296 @@ export async function handleGraphApiRequest({
|
|
|
178
178
|
sendJson(response, 200, await app.upsertPersonalProject(await readJson(request)));
|
|
179
179
|
return true;
|
|
180
180
|
}
|
|
181
|
+
if (url.pathname === '/api/project-agents' && request.method === 'GET') {
|
|
182
|
+
sendJson(response, 200, await app.listProjectAgents({
|
|
183
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
184
|
+
personalProjectId: url.searchParams.get('personalProjectId'),
|
|
185
|
+
status: url.searchParams.get('status'),
|
|
186
|
+
capability: url.searchParams.get('capability')
|
|
187
|
+
}));
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
if (url.pathname === '/api/project-agents' && request.method === 'PUT') {
|
|
191
|
+
sendJson(response, 200, await app.upsertProjectAgent(await readJson(request)));
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
if (url.pathname === '/api/project-agent-context' && request.method === 'POST') {
|
|
195
|
+
sendJson(response, 200, await app.getProjectAgentContext(await readJson(request)));
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
const projectAgentPath = url.pathname.match(/^\/api\/project-agents\/([^/]+)$/);
|
|
199
|
+
if (projectAgentPath && request.method === 'GET') {
|
|
200
|
+
sendJson(response, 200, await app.getProjectAgent({
|
|
201
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
202
|
+
personalProjectId: url.searchParams.get('personalProjectId'),
|
|
203
|
+
agentId: decodeURIComponent(projectAgentPath[1])
|
|
204
|
+
}));
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
if (projectAgentPath && request.method === 'DELETE') {
|
|
208
|
+
sendJson(response, 200, await app.deleteProjectAgent({
|
|
209
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
210
|
+
agentId: decodeURIComponent(projectAgentPath[1]),
|
|
211
|
+
reason: url.searchParams.get('reason') ?? 'archived by user'
|
|
212
|
+
}));
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
if (url.pathname === '/api/project-agents/test-cleanup' && request.method === 'POST') {
|
|
216
|
+
sendJson(response, 200, await app.cleanupProjectAgentTestRoles({
|
|
217
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
218
|
+
testSource: url.searchParams.get('testSource')
|
|
219
|
+
}));
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
if (url.pathname === '/api/project-agent-assignments' && request.method === 'GET') {
|
|
223
|
+
sendJson(response, 200, await app.listProjectAgentAssignments({
|
|
224
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
225
|
+
personalProjectId: url.searchParams.get('personalProjectId'),
|
|
226
|
+
agentId: url.searchParams.get('agentId'),
|
|
227
|
+
status: url.searchParams.get('status')
|
|
228
|
+
}));
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
if (url.pathname === '/api/project-agent-assignments' && request.method === 'POST') {
|
|
232
|
+
sendJson(response, 200, await app.createProjectAgentAssignment(await readJson(request)));
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
const projectAgentAssignmentPath = url.pathname.match(
|
|
236
|
+
/^\/api\/project-agent-assignments\/([^/]+)\/(end|replace)$/
|
|
237
|
+
);
|
|
238
|
+
if (projectAgentAssignmentPath && request.method === 'POST') {
|
|
239
|
+
const body = await readJson(request);
|
|
240
|
+
const input = {
|
|
241
|
+
...body,
|
|
242
|
+
assignmentId: decodeURIComponent(projectAgentAssignmentPath[1])
|
|
243
|
+
};
|
|
244
|
+
const result = projectAgentAssignmentPath[2] === 'end'
|
|
245
|
+
? await app.endProjectAgentAssignment(input)
|
|
246
|
+
: await app.replaceProjectAgentAssignment(input);
|
|
247
|
+
sendJson(response, 200, result);
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
if (url.pathname === '/api/project-agent-tasks' && request.method === 'GET') {
|
|
251
|
+
sendJson(response, 200, await app.listProjectAgentTasks({
|
|
252
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
253
|
+
personalProjectId: url.searchParams.get('personalProjectId'),
|
|
254
|
+
agentId: url.searchParams.get('agentId'),
|
|
255
|
+
status: url.searchParams.get('status'),
|
|
256
|
+
limit: numberParam(url, 'limit', null)
|
|
257
|
+
}));
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
if (url.pathname === '/api/project-agent-tasks' && request.method === 'POST') {
|
|
261
|
+
sendJson(response, 200, await app.submitProjectAgentTask(await readJson(request)));
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
const projectAgentTaskPath = url.pathname.match(/^\/api\/project-agent-tasks\/([^/]+)$/);
|
|
265
|
+
if (projectAgentTaskPath && request.method === 'GET') {
|
|
266
|
+
sendJson(response, 200, await app.viewProjectAgentTask({
|
|
267
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
268
|
+
taskId: decodeURIComponent(projectAgentTaskPath[1]),
|
|
269
|
+
includeEvents: url.searchParams.get('includeEvents') !== 'false'
|
|
270
|
+
}));
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
if (url.pathname === '/api/project-agent-activity' && request.method === 'GET') {
|
|
274
|
+
sendJson(response, 200, await app.viewProjectAgentActivity({
|
|
275
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
276
|
+
agentId: url.searchParams.get('agentId'),
|
|
277
|
+
fromDate: url.searchParams.get('fromDate'),
|
|
278
|
+
toDate: url.searchParams.get('toDate')
|
|
279
|
+
}));
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
if (url.pathname === '/api/project-agent-activity' && request.method === 'POST') {
|
|
283
|
+
sendJson(response, 200, await app.recordProjectAgentTaskActivity(await readJson(request)));
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
if (url.pathname === '/api/project-agent-coordination-policy' && request.method === 'GET') {
|
|
287
|
+
sendJson(response, 200, await app.getProjectAgentCoordinationPolicy({
|
|
288
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
289
|
+
personalProjectId: url.searchParams.get('personalProjectId')
|
|
290
|
+
}));
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
if (url.pathname === '/api/project-agent-coordination-policy' &&
|
|
294
|
+
(request.method === 'PUT' || request.method === 'PATCH')) {
|
|
295
|
+
sendJson(response, 200, await app.updateProjectAgentCoordinationPolicy(await readJson(request)));
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
if (url.pathname === '/api/project-agent-recruitment-policy' && request.method === 'GET') {
|
|
299
|
+
sendJson(response, 200, await app.getProjectAgentRecruitmentPolicy({
|
|
300
|
+
personalSpaceId: url.searchParams.get('personalSpaceId')
|
|
301
|
+
}));
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
if (url.pathname === '/api/project-agent-recruitment-policy' &&
|
|
305
|
+
(request.method === 'PUT' || request.method === 'PATCH')) {
|
|
306
|
+
sendJson(response, 200, await app.updateProjectAgentRecruitmentPolicy(await readJson(request)));
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
if (url.pathname === '/api/project-agent-recruitments' && request.method === 'GET') {
|
|
310
|
+
sendJson(response, 200, await app.listProjectAgentRecruitments({
|
|
311
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
312
|
+
personalProjectId: url.searchParams.get('personalProjectId'),
|
|
313
|
+
taskId: url.searchParams.get('taskId'),
|
|
314
|
+
status: url.searchParams.get('status')
|
|
315
|
+
}));
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
if (url.pathname === '/api/project-agent-recruitments/decision' && request.method === 'POST') {
|
|
319
|
+
sendJson(response, 200, await app.decideProjectAgentRecruitment(await readJson(request)));
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
if (url.pathname === '/api/executors' && request.method === 'GET') {
|
|
323
|
+
sendJson(response, 200, await app.listExecutors({
|
|
324
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
325
|
+
capability: url.searchParams.get('capability'),
|
|
326
|
+
availableOnly: url.searchParams.get('availableOnly') === 'true'
|
|
327
|
+
}));
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
if (url.pathname === '/api/executors' && request.method === 'PUT') {
|
|
331
|
+
sendJson(response, 200, await app.upsertExecutor(await readJson(request)));
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
const executorPath = url.pathname.match(/^\/api\/executors\/([^/]+)$/);
|
|
335
|
+
if (executorPath && request.method === 'GET') {
|
|
336
|
+
sendJson(response, 200, await app.getExecutor({
|
|
337
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
338
|
+
executorId: decodeURIComponent(executorPath[1])
|
|
339
|
+
}));
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
if (executorPath && request.method === 'DELETE') {
|
|
343
|
+
sendJson(response, 200, await app.deleteExecutor({
|
|
344
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
345
|
+
executorId: decodeURIComponent(executorPath[1])
|
|
346
|
+
}));
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
if (url.pathname === '/api/executors/preflight' && request.method === 'POST') {
|
|
350
|
+
sendJson(response, 200, await app.preflightExecutor(await readJson(request)));
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
if (url.pathname === '/api/executors/authorization' && request.method === 'POST') {
|
|
354
|
+
sendJson(response, 200, await app.authorizeExecutor(await readJson(request)));
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
if (url.pathname === '/api/executors/health' && request.method === 'POST') {
|
|
358
|
+
sendJson(response, 200, await app.reportExecutorHealth(await readJson(request)));
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
if (url.pathname === '/api/project-agent-executor-actuals' && request.method === 'POST') {
|
|
362
|
+
sendJson(response, 200, await app.recordProjectAgentExecutorActual(await readJson(request)));
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
if (url.pathname === '/api/executor-routing-rules' && request.method === 'GET') {
|
|
366
|
+
sendJson(response, 200, await app.listExecutorRoutingRules({
|
|
367
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
368
|
+
scope: url.searchParams.get('scope'),
|
|
369
|
+
personalProjectId: url.searchParams.get('personalProjectId'),
|
|
370
|
+
taskId: url.searchParams.get('taskId'),
|
|
371
|
+
status: url.searchParams.get('status')
|
|
372
|
+
}));
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
if (url.pathname === '/api/executor-routing-rules' && request.method === 'PUT') {
|
|
376
|
+
sendJson(response, 200, await app.upsertExecutorRoutingRule(await readJson(request)));
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
const executorRoutingRulePath = url.pathname.match(
|
|
380
|
+
/^\/api\/executor-routing-rules\/([^/]+)$/
|
|
381
|
+
);
|
|
382
|
+
if (executorRoutingRulePath && request.method === 'GET') {
|
|
383
|
+
sendJson(response, 200, await app.getExecutorRoutingRule({
|
|
384
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
385
|
+
ruleId: decodeURIComponent(executorRoutingRulePath[1])
|
|
386
|
+
}));
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
if (executorRoutingRulePath && request.method === 'PATCH') {
|
|
390
|
+
const body = await readJson(request);
|
|
391
|
+
sendJson(response, 200, await app.updateExecutorRoutingRule({
|
|
392
|
+
...body,
|
|
393
|
+
personalSpaceId: body.personalSpaceId ?? url.searchParams.get('personalSpaceId'),
|
|
394
|
+
ruleId: decodeURIComponent(executorRoutingRulePath[1])
|
|
395
|
+
}));
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
if (executorRoutingRulePath && request.method === 'DELETE') {
|
|
399
|
+
sendJson(response, 200, await app.deleteExecutorRoutingRule({
|
|
400
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
401
|
+
ruleId: decodeURIComponent(executorRoutingRulePath[1])
|
|
402
|
+
}));
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
if (url.pathname === '/api/project-agent-routing-learning' && request.method === 'GET') {
|
|
406
|
+
sendJson(response, 200, await app.listProjectAgentRoutingLearning({
|
|
407
|
+
personalSpaceId: url.searchParams.get('personalSpaceId'),
|
|
408
|
+
personalProjectId: url.searchParams.get('personalProjectId'),
|
|
409
|
+
workKind: url.searchParams.get('workKind'),
|
|
410
|
+
agentId: url.searchParams.get('agentId'),
|
|
411
|
+
executorId: url.searchParams.get('executorId')
|
|
412
|
+
}));
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
const projectAgentLearningPath = url.pathname.match(
|
|
416
|
+
/^\/api\/project-agent-learning\/([^/]+)$/
|
|
417
|
+
);
|
|
418
|
+
if (projectAgentLearningPath && request.method === 'PATCH') {
|
|
419
|
+
const body = await readJson(request);
|
|
420
|
+
const evidenceId = decodeURIComponent(projectAgentLearningPath[1]);
|
|
421
|
+
const action = body.action;
|
|
422
|
+
if (!['ignore', 'reset'].includes(action)) {
|
|
423
|
+
throw new TypeError('Project Agent learning action must be ignore or reset');
|
|
424
|
+
}
|
|
425
|
+
const personalSpaceId = body.personalSpaceId ??
|
|
426
|
+
url.searchParams.get('personalSpaceId') ?? app.config?.personal?.spaceId;
|
|
427
|
+
const personalProjectId = body.personalProjectId ??
|
|
428
|
+
url.searchParams.get('personalProjectId');
|
|
429
|
+
const agentId = body.agentId ?? url.searchParams.get('agentId');
|
|
430
|
+
if (!personalSpaceId || !personalProjectId || !agentId) {
|
|
431
|
+
throw new TypeError(
|
|
432
|
+
'Project Agent learning updates require personalSpaceId, personalProjectId, and agentId'
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
const idempotencyKey = body.idempotencyKey ??
|
|
436
|
+
`console-learning:${evidenceId}:${action}`;
|
|
437
|
+
const reason = body.reason ?? `Console requested ${action} for explicit evidence`;
|
|
438
|
+
const input = {
|
|
439
|
+
...body,
|
|
440
|
+
personalSpaceId,
|
|
441
|
+
personalProjectId,
|
|
442
|
+
agentId,
|
|
443
|
+
evidenceId,
|
|
444
|
+
idempotencyKey,
|
|
445
|
+
reason
|
|
446
|
+
};
|
|
447
|
+
if (action === 'ignore') {
|
|
448
|
+
sendJson(response, 200, await app.ignoreProjectAgentRoutingLearning(input));
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
if (!input.workKind || !input.executorId || !input.resetAt) {
|
|
452
|
+
throw new TypeError(
|
|
453
|
+
'Project Agent learning reset requires workKind, executorId, and resetAt'
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
sendJson(response, 200, await app.resetProjectAgentRoutingLearning(input));
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
if (url.pathname === '/api/project-agent-routing-learning/ignore' && request.method === 'POST') {
|
|
460
|
+
sendJson(response, 200, await app.ignoreProjectAgentRoutingLearning(await readJson(request)));
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
463
|
+
if (url.pathname === '/api/project-agent-routing-learning/reset' && request.method === 'POST') {
|
|
464
|
+
sendJson(response, 200, await app.resetProjectAgentRoutingLearning(await readJson(request)));
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
if (url.pathname === '/api/project-agent-routing-outcomes' && request.method === 'POST') {
|
|
468
|
+
sendJson(response, 200, await app.recordProjectAgentTaskOutcome(await readJson(request)));
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
181
471
|
if (url.pathname === '/api/projects/publish' && request.method === 'POST') {
|
|
182
472
|
sendJson(response, 200, await app.publishPersonalProject(await readJson(request)));
|
|
183
473
|
return true;
|