@mrpatronz/nexusflow 2.2.0 → 2.3.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 +80 -17
- package/dist/commands/ui.d.ts +1 -0
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +24 -13
- package/dist/commands/ui.js.map +1 -1
- package/dist/commands/ui.test.d.ts +2 -0
- package/dist/commands/ui.test.d.ts.map +1 -0
- package/dist/commands/ui.test.js +58 -0
- package/dist/commands/ui.test.js.map +1 -0
- package/dist/core/workspace-skills-workflow.integration.test.d.ts +2 -0
- package/dist/core/workspace-skills-workflow.integration.test.d.ts.map +1 -0
- package/dist/core/workspace-skills-workflow.integration.test.js +162 -0
- package/dist/core/workspace-skills-workflow.integration.test.js.map +1 -0
- package/dist/core/worktree.test.js +1 -1
- package/dist/core/worktree.test.js.map +1 -1
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +4 -8
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/skills-generator.d.ts +2 -2
- package/dist/generators/skills-generator.d.ts.map +1 -1
- package/dist/generators/skills-generator.js +84 -89
- package/dist/generators/skills-generator.js.map +1 -1
- package/dist/generators/skills-generator.test.d.ts +2 -0
- package/dist/generators/skills-generator.test.d.ts.map +1 -0
- package/dist/generators/skills-generator.test.js +79 -0
- package/dist/generators/skills-generator.test.js.map +1 -0
- package/dist/gui/assets/AgentsPage-BtrTgIyU.js +3 -0
- package/dist/gui/assets/{DashboardPage-CUspfCap.js → DashboardPage-CeUkMdxc.js} +1 -1
- package/dist/gui/assets/{GettingStartedPage-BqtgARZW.js → GettingStartedPage-YwJXpsc6.js} +1 -1
- package/dist/gui/assets/ProjectsPage-D8kEHb-m.js +1 -0
- package/dist/gui/assets/ScaffoldRepoInline-ij7JLzmx.js +1 -0
- package/dist/gui/assets/SettingsPage-BQhAP4go.js +1 -0
- package/dist/gui/assets/SkillsPage-DJ-dXfcC.js +6 -0
- package/dist/gui/assets/StartWorkPage-DGWZzF4H.js +1 -0
- package/dist/gui/assets/{StrategiesPage-D0Y6A4Tw.js → StrategiesPage-CLOjDRbX.js} +2 -2
- package/dist/gui/assets/WorkspaceLauncher-CjNI4vqn.js +1 -0
- package/dist/gui/assets/WorkspacesPage-MDzm2JUh.js +6 -0
- package/dist/gui/assets/alert-dialog-DjwFcE6b.js +1 -0
- package/dist/gui/assets/bot-wH0FKlic.js +1 -0
- package/dist/gui/assets/chevron-down-DDmhvRLr.js +1 -0
- package/dist/gui/assets/code-xml-Chu1p81J.js +1 -0
- package/dist/gui/assets/index-CfQEnn52.js +52 -0
- package/dist/gui/assets/index-k7inKaui.css +2 -0
- package/dist/gui/assets/{spinner-DXt6mnJk.js → spinner-BCEaGbib.js} +1 -1
- package/dist/gui/assets/terminal-gK6BMl3E.js +1 -0
- package/dist/gui/assets/{textarea-BLU5HXmZ.js → textarea-D3-elOAa.js} +1 -1
- package/dist/gui/assets/{useAriaLabelledBy-CjNlctb9.js → useAriaLabelledBy-DmwmZIqb.js} +1 -1
- package/dist/gui/assets/useCompositeListItem-CZnlZ-eF.js +1 -0
- package/dist/gui/assets/useValueChanged-BfI2s7NX.js +1 -0
- package/dist/gui/assets/zap-FQrDnrgb.js +1 -0
- package/dist/gui/index.html +6 -4
- package/dist/resources/agents-catalog.d.ts +7 -0
- package/dist/resources/agents-catalog.d.ts.map +1 -0
- package/dist/resources/agents-catalog.js +141 -0
- package/dist/resources/agents-catalog.js.map +1 -0
- package/dist/resources/agents-catalog.test.d.ts +2 -0
- package/dist/resources/agents-catalog.test.d.ts.map +1 -0
- package/dist/resources/agents-catalog.test.js +50 -0
- package/dist/resources/agents-catalog.test.js.map +1 -0
- package/dist/resources/codex-agent.d.ts +6 -0
- package/dist/resources/codex-agent.d.ts.map +1 -0
- package/dist/resources/codex-agent.js +55 -0
- package/dist/resources/codex-agent.js.map +1 -0
- package/dist/resources/codex-agent.test.d.ts +2 -0
- package/dist/resources/codex-agent.test.d.ts.map +1 -0
- package/dist/resources/codex-agent.test.js +27 -0
- package/dist/resources/codex-agent.test.js.map +1 -0
- package/dist/resources/contracts.d.ts +116 -0
- package/dist/resources/contracts.d.ts.map +1 -0
- package/dist/resources/contracts.js +103 -0
- package/dist/resources/contracts.js.map +1 -0
- package/dist/resources/fs-safety.d.ts +11 -0
- package/dist/resources/fs-safety.d.ts.map +1 -0
- package/dist/resources/fs-safety.js +77 -0
- package/dist/resources/fs-safety.js.map +1 -0
- package/dist/resources/materializer.d.ts +17 -0
- package/dist/resources/materializer.d.ts.map +1 -0
- package/dist/resources/materializer.js +439 -0
- package/dist/resources/materializer.js.map +1 -0
- package/dist/resources/materializer.test.d.ts +2 -0
- package/dist/resources/materializer.test.d.ts.map +1 -0
- package/dist/resources/materializer.test.js +149 -0
- package/dist/resources/materializer.test.js.map +1 -0
- package/dist/resources/service.d.ts +8 -0
- package/dist/resources/service.d.ts.map +1 -0
- package/dist/resources/service.js +45 -0
- package/dist/resources/service.js.map +1 -0
- package/dist/resources/service.test.d.ts +2 -0
- package/dist/resources/service.test.d.ts.map +1 -0
- package/dist/resources/service.test.js +58 -0
- package/dist/resources/service.test.js.map +1 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +310 -4
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +365 -5
- package/dist/server.test.js.map +1 -1
- package/dist/types.d.ts +107 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/resources.d.ts +2 -1
- package/dist/utils/resources.d.ts.map +1 -1
- package/dist/utils/resources.js +4 -3
- package/dist/utils/resources.js.map +1 -1
- package/dist/utils/session-finder.d.ts +6 -0
- package/dist/utils/session-finder.d.ts.map +1 -1
- package/dist/utils/session-finder.js +56 -0
- package/dist/utils/session-finder.js.map +1 -1
- package/dist/utils/session-finder.test.js +34 -1
- package/dist/utils/session-finder.test.js.map +1 -1
- package/dist/utils/skills-catalog.d.ts +77 -0
- package/dist/utils/skills-catalog.d.ts.map +1 -0
- package/dist/utils/skills-catalog.js +871 -0
- package/dist/utils/skills-catalog.js.map +1 -0
- package/dist/utils/skills-catalog.test.d.ts +2 -0
- package/dist/utils/skills-catalog.test.d.ts.map +1 -0
- package/dist/utils/skills-catalog.test.js +281 -0
- package/dist/utils/skills-catalog.test.js.map +1 -0
- package/dist/utils/workspace-launch.d.ts.map +1 -1
- package/dist/utils/workspace-launch.js +22 -1
- package/dist/utils/workspace-launch.js.map +1 -1
- package/dist/utils/workspace-launch.test.js +36 -2
- package/dist/utils/workspace-launch.test.js.map +1 -1
- package/package.json +4 -1
- package/dist/gui/assets/ProjectsPage-UBoQxI2G.js +0 -1
- package/dist/gui/assets/ScaffoldRepoInline-DqoourJe.js +0 -1
- package/dist/gui/assets/SettingsPage-BZl24tqD.js +0 -1
- package/dist/gui/assets/StartWorkPage-BGNFdBfj.js +0 -1
- package/dist/gui/assets/WorkspaceLauncher-Cxv0O_wt.js +0 -1
- package/dist/gui/assets/WorkspacesPage-Cvb1rOeh.js +0 -6
- package/dist/gui/assets/index-CllPiiFL.js +0 -52
- package/dist/gui/assets/index-DGCBhMAn.css +0 -2
- package/dist/gui/assets/useCompositeListItem-DWGFLKqA.js +0 -1
- /package/dist/{resources → static-resources}/workflows/plan-implement-review.md +0 -0
- /package/dist/{resources → static-resources}/workflows/research-verify.md +0 -0
- /package/dist/{resources → static-resources}/workflows/solo-developer.md +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materializer.test.js","sourceRoot":"","sources":["../../src/resources/materializer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class ResourceSelectionError extends Error {
|
|
2
|
+
readonly missingSkills: string[];
|
|
3
|
+
readonly missingAgents: string[];
|
|
4
|
+
constructor(missingSkills: string[], missingAgents: string[]);
|
|
5
|
+
}
|
|
6
|
+
export declare function withResourceAdministrationLock<T>(operation: () => Promise<T>): Promise<T>;
|
|
7
|
+
export declare function validateResourceSelections(enabledSkills: string[], enabledAgents: string[]): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/resources/service.ts"],"names":[],"mappings":"AAQA,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,SAAgB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxC,SAAgB,aAAa,EAAE,MAAM,EAAE,CAAC;gBAE5B,aAAa,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE;CAU7D;AAED,wBAAsB,8BAA8B,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAgB/F;AAED,wBAAsB,0BAA0B,CAC9C,aAAa,EAAE,MAAM,EAAE,EACvB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CASf"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { acquireLock, createMutationQueue } from '../core/locks.js';
|
|
3
|
+
import { getAllSkills, getNexusFlowHome } from '../utils/skills-catalog.js';
|
|
4
|
+
import { getAllAgents } from './agents-catalog.js';
|
|
5
|
+
const runResourceAdministration = createMutationQueue();
|
|
6
|
+
export class ResourceSelectionError extends Error {
|
|
7
|
+
missingSkills;
|
|
8
|
+
missingAgents;
|
|
9
|
+
constructor(missingSkills, missingAgents) {
|
|
10
|
+
const parts = [
|
|
11
|
+
missingSkills.length ? `skills: ${missingSkills.join(', ')}` : '',
|
|
12
|
+
missingAgents.length ? `agents: ${missingAgents.join(', ')}` : '',
|
|
13
|
+
].filter(Boolean);
|
|
14
|
+
super(`Selected resources are not available (${parts.join('; ')}).`);
|
|
15
|
+
this.name = 'ResourceSelectionError';
|
|
16
|
+
this.missingSkills = missingSkills;
|
|
17
|
+
this.missingAgents = missingAgents;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export async function withResourceAdministrationLock(operation) {
|
|
21
|
+
return runResourceAdministration(async () => {
|
|
22
|
+
const release = await acquireLock(path.join(getNexusFlowHome(), '.locks', 'resource-administration.lock'), {
|
|
23
|
+
staleMs: 60_000,
|
|
24
|
+
timeoutMs: 15_000,
|
|
25
|
+
timeoutMessage: 'Timed out waiting for resource administration.',
|
|
26
|
+
});
|
|
27
|
+
try {
|
|
28
|
+
return await operation();
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
await release();
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export async function validateResourceSelections(enabledSkills, enabledAgents) {
|
|
36
|
+
const [skills, agents] = await Promise.all([getAllSkills(), getAllAgents()]);
|
|
37
|
+
const skillIds = new Set(skills.map((skill) => skill.id));
|
|
38
|
+
const agentIds = new Set(agents.map((agent) => agent.id));
|
|
39
|
+
const missingSkills = [...new Set(enabledSkills)].filter((id) => !skillIds.has(id));
|
|
40
|
+
const missingAgents = [...new Set(enabledAgents)].filter((id) => !agentIds.has(id));
|
|
41
|
+
if (missingSkills.length || missingAgents.length) {
|
|
42
|
+
throw new ResourceSelectionError(missingSkills, missingAgents);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/resources/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,yBAAyB,GAAG,mBAAmB,EAAE,CAAC;AAExD,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/B,aAAa,CAAW;IACxB,aAAa,CAAW;IAExC,YAAY,aAAuB,EAAE,aAAuB;QAC1D,MAAM,KAAK,GAAG;YACZ,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;YACjE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;SAClE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClB,KAAK,CAAC,yCAAyC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrE,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAI,SAA2B;IACjF,OAAO,yBAAyB,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,OAAO,GAAG,MAAM,WAAW,CAC/B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,8BAA8B,CAAC,EACvE;YACE,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,MAAM;YACjB,cAAc,EAAE,gDAAgD;SACjE,CACF,CAAC;QACF,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,EAAE,CAAC;QAC3B,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,aAAuB,EACvB,aAAuB;IAEvB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACpF,IAAI,aAAa,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;QACjD,MAAM,IAAI,sBAAsB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACjE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.test.d.ts","sourceRoot":"","sources":["../../src/resources/service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import fse from 'fs-extra';
|
|
6
|
+
import { saveAgent } from './agents-catalog.js';
|
|
7
|
+
import { validateResourceSelections, withResourceAdministrationLock, } from './service.js';
|
|
8
|
+
describe('resource administration service', () => {
|
|
9
|
+
let tempHome;
|
|
10
|
+
const originalHome = process.env.NEXUSFLOW_HOME;
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), 'nexusflow-resource-service-'));
|
|
13
|
+
process.env.NEXUSFLOW_HOME = tempHome;
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
if (originalHome === undefined)
|
|
17
|
+
delete process.env.NEXUSFLOW_HOME;
|
|
18
|
+
else
|
|
19
|
+
process.env.NEXUSFLOW_HOME = originalHome;
|
|
20
|
+
await fse.remove(tempHome);
|
|
21
|
+
});
|
|
22
|
+
it('rejects missing selections and accepts existing underscore-style agents', async () => {
|
|
23
|
+
await saveAgent({
|
|
24
|
+
name: 'docs_researcher',
|
|
25
|
+
category: 'general',
|
|
26
|
+
description: 'Use when researching docs.',
|
|
27
|
+
developerInstructions: 'Research official documentation.',
|
|
28
|
+
});
|
|
29
|
+
await expect(validateResourceSelections(['pr-review-toolkit'], ['docs_researcher'])).resolves.toBeUndefined();
|
|
30
|
+
await expect(validateResourceSelections(['missing-skill'], ['missing_agent'])).rejects.toMatchObject({
|
|
31
|
+
missingSkills: ['missing-skill'],
|
|
32
|
+
missingAgents: ['missing_agent'],
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it('serializes administration operations under one shared boundary', async () => {
|
|
36
|
+
const events = [];
|
|
37
|
+
let releaseFirst;
|
|
38
|
+
const firstGate = new Promise((resolve) => { releaseFirst = resolve; });
|
|
39
|
+
let firstStarted;
|
|
40
|
+
const started = new Promise((resolve) => { firstStarted = resolve; });
|
|
41
|
+
const first = withResourceAdministrationLock(async () => {
|
|
42
|
+
events.push('first-start');
|
|
43
|
+
firstStarted();
|
|
44
|
+
await firstGate;
|
|
45
|
+
events.push('first-end');
|
|
46
|
+
});
|
|
47
|
+
await started;
|
|
48
|
+
const second = withResourceAdministrationLock(async () => {
|
|
49
|
+
events.push('second-start');
|
|
50
|
+
events.push('second-end');
|
|
51
|
+
});
|
|
52
|
+
expect(events).toEqual(['first-start']);
|
|
53
|
+
releaseFirst();
|
|
54
|
+
await Promise.all([first, second]);
|
|
55
|
+
expect(events).toEqual(['first-start', 'first-end', 'second-start', 'second-end']);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.test.js","sourceRoot":"","sources":["../../src/resources/service.test.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -23,6 +23,11 @@ export declare class PathAccessError extends Error {
|
|
|
23
23
|
}
|
|
24
24
|
/** Safe workspace directory for a route `:id`, contained within workspacesDir. */
|
|
25
25
|
export declare function resolveWorkspacePath(workspacesDir: string, id: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Claude's documented `/desktop` transfer is narrower than its URI handler:
|
|
28
|
+
* it requires macOS or x64 Windows, a subscription login, and a usable CLI.
|
|
29
|
+
*/
|
|
30
|
+
export declare function canOfferClaudeDesktopTransfer(platform?: NodeJS.Platform, architecture?: NodeJS.Architecture, env?: NodeJS.ProcessEnv, isCliConfigured?: () => boolean): boolean;
|
|
26
31
|
/** Safe sub-repo path for a repo name, contained within the workspace. */
|
|
27
32
|
export declare function resolveRepoPath(workspacePath: string, repoName: string): string;
|
|
28
33
|
/**
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AA0C5B,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AA4EjF,eAAO,MAAM,GAAG,4EAAa,CAAC;AAc9B,mGAAmG;AACnG,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,GACvD,MAAM,GAAG,IAAI,CAUf;AAED,gFAAgF;AAChF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;IAEhB,QAAQ,IAAI,OAAO;IAMnB,MAAM,IAAI,IAAI;IAId,QAAQ,IAAI,OAAO;CAG3B;AAuKD,yEAAyE;AACzE,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,SAA2B;CAI/C;AAcD,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9E;AAID;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,YAAY,GAAE,MAAM,CAAC,YAA2B,EAChD,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,eAAe,GAAE,MAAM,OAAmF,GACzG,OAAO,CAeT;AA8BD,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE/E;AAsDD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAc7D;AA4/DD,wBAAgB,WAAW,CACzB,IAAI,SAAO,EACX,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,CA0BxC"}
|
package/dist/server.js
CHANGED
|
@@ -30,7 +30,7 @@ import { generateContextFiles } from './generators/index.js';
|
|
|
30
30
|
import { detectAIAssistants } from './utils/detect-ai.js';
|
|
31
31
|
import { detectEditors } from './utils/detect-editors.js';
|
|
32
32
|
import { buildWorkspaceLaunchPrompt, detectWorkspaceLaunchTargets, launchTargetIdForEditorCommand, launchWorkspaceTarget, } from './utils/workspace-launch.js';
|
|
33
|
-
import { canOpenCodexSessionInWorkspace, findSessions, getSessionTranscript } from './utils/session-finder.js';
|
|
33
|
+
import { canOpenCodexSessionInWorkspace, canTransferClaudeSessionInWorkspace, findSessions, getSessionTranscript, } from './utils/session-finder.js';
|
|
34
34
|
import { ProviderRegistry } from './agent/adapters.js';
|
|
35
35
|
import { isValidSessionUuid } from './agent/session.js';
|
|
36
36
|
import { getRepoStatus } from './utils/multi-git.js';
|
|
@@ -43,6 +43,10 @@ import { addSchedule, loadSchedules, nextDueAt, parseInterval, removeSchedule, r
|
|
|
43
43
|
import { detectAllServices, detectOrchestrationTools, startServices, stopServices, startService, stopService, restartService, startOrchestrator, stopOrchestrator, tailLogFile, loadRunningState, getPm2List, } from './orchestration/index.js';
|
|
44
44
|
import { checkForUpdates, getCurrentVersion, getToolsStatus } from './utils/update-check.js';
|
|
45
45
|
import { getWorkflowTemplates, saveWorkflowTemplate, deleteWorkflowTemplate } from './utils/workflows.js';
|
|
46
|
+
import { getSkillCategories, saveSkillCategory, deleteSkillCategory, getAllSkills, saveSkill, deleteSkill, getWorkspaceSkillsConfig, saveWorkspaceSkillsConfig, WorkspaceResourceRevisionError, } from './utils/skills-catalog.js';
|
|
47
|
+
import { deleteAgent, getAllAgents, importAgentToml, saveAgent, } from './resources/agents-catalog.js';
|
|
48
|
+
import { ResourceConflictError } from './resources/materializer.js';
|
|
49
|
+
import { ResourceSelectionError, validateResourceSelections, withResourceAdministrationLock, } from './resources/service.js';
|
|
46
50
|
import { suggestWorkflow } from './utils/workflow-advisor.js';
|
|
47
51
|
// Resolve static files directory
|
|
48
52
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -282,6 +286,27 @@ function assertWithin(baseDir, target) {
|
|
|
282
286
|
export function resolveWorkspacePath(workspacesDir, id) {
|
|
283
287
|
return assertWithin(workspacesDir, path.join(workspacesDir, id));
|
|
284
288
|
}
|
|
289
|
+
const DESKTOP_HANDOFF_SCAN_LIMIT = 20;
|
|
290
|
+
/**
|
|
291
|
+
* Claude's documented `/desktop` transfer is narrower than its URI handler:
|
|
292
|
+
* it requires macOS or x64 Windows, a subscription login, and a usable CLI.
|
|
293
|
+
*/
|
|
294
|
+
export function canOfferClaudeDesktopTransfer(platform = process.platform, architecture = process.arch, env = process.env, isCliConfigured = () => ProviderRegistry.getProvider('claude-cli')?.isConfigured() === true) {
|
|
295
|
+
const supportedPlatform = platform === 'darwin' || (platform === 'win32' && architecture === 'x64');
|
|
296
|
+
const usesUnsupportedAuth = Boolean(env.ANTHROPIC_API_KEY
|
|
297
|
+
|| env.ANTHROPIC_AUTH_TOKEN
|
|
298
|
+
|| env.CLAUDE_CODE_USE_BEDROCK === '1'
|
|
299
|
+
|| env.CLAUDE_CODE_USE_VERTEX === '1'
|
|
300
|
+
|| env.CLAUDE_CODE_USE_FOUNDRY === '1');
|
|
301
|
+
if (!supportedPlatform || usesUnsupportedAuth)
|
|
302
|
+
return false;
|
|
303
|
+
try {
|
|
304
|
+
return isCliConfigured();
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
285
310
|
/**
|
|
286
311
|
* Resolve a launch path through the filesystem and require it to be the exact
|
|
287
312
|
* workspace declared by its manifest. This prevents symlink escapes and stops
|
|
@@ -316,9 +341,49 @@ function errorResponse(c, error) {
|
|
|
316
341
|
if (error instanceof PathAccessError) {
|
|
317
342
|
return c.json({ error: error.message }, 400);
|
|
318
343
|
}
|
|
344
|
+
if (error instanceof ResourceConflictError || error instanceof WorkspaceResourceRevisionError) {
|
|
345
|
+
return c.json({
|
|
346
|
+
error: error.message,
|
|
347
|
+
conflicts: error instanceof ResourceConflictError ? error.conflicts : undefined,
|
|
348
|
+
}, 409);
|
|
349
|
+
}
|
|
350
|
+
if (error instanceof ResourceSelectionError) {
|
|
351
|
+
return c.json({
|
|
352
|
+
error: error.message,
|
|
353
|
+
missingSkills: error.missingSkills,
|
|
354
|
+
missingAgents: error.missingAgents,
|
|
355
|
+
}, 400);
|
|
356
|
+
}
|
|
319
357
|
const msg = error instanceof Error ? error.message : String(error);
|
|
320
358
|
return c.json({ error: msg }, 500);
|
|
321
359
|
}
|
|
360
|
+
async function resolveExactWorkspaceById(workspacesDir, id) {
|
|
361
|
+
const candidate = resolveWorkspacePath(workspacesDir, id);
|
|
362
|
+
try {
|
|
363
|
+
return await resolveExactLaunchWorkspace(workspacesDir, candidate);
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
const code = typeof error === 'object' && error !== null && 'code' in error
|
|
367
|
+
? String(error.code)
|
|
368
|
+
: undefined;
|
|
369
|
+
if (code === 'ENOENT')
|
|
370
|
+
return null;
|
|
371
|
+
throw error;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
async function findResourceAssignments(workspacesDir, resourceId, kind) {
|
|
375
|
+
const assignments = [];
|
|
376
|
+
for (const workspace of await listWorkspaces(workspacesDir)) {
|
|
377
|
+
const workspacePath = await resolveExactWorkspaceById(workspacesDir, workspace.id);
|
|
378
|
+
if (!workspacePath)
|
|
379
|
+
continue;
|
|
380
|
+
const selection = await getWorkspaceSkillsConfig(workspacePath);
|
|
381
|
+
const enabled = kind === 'skill' ? selection.enabledSkills : selection.enabledAgents ?? [];
|
|
382
|
+
if (enabled.includes(resourceId))
|
|
383
|
+
assignments.push(workspace.id);
|
|
384
|
+
}
|
|
385
|
+
return assignments;
|
|
386
|
+
}
|
|
322
387
|
/**
|
|
323
388
|
* Restrict the self-update download to GitHub release hosts over HTTPS so a
|
|
324
389
|
* cross-origin caller cannot make the server fetch and later execute an
|
|
@@ -1580,13 +1645,69 @@ app.post('/api/workspace/:id/resume', async (c) => {
|
|
|
1580
1645
|
app.get('/api/workspace/:id/sessions', async (c) => {
|
|
1581
1646
|
try {
|
|
1582
1647
|
const id = decodeURIComponent(c.req.param('id'));
|
|
1648
|
+
const limitParam = c.req.query('limit');
|
|
1649
|
+
const desktopHandoffOnly = c.req.query('desktopHandoffOnly') === 'true';
|
|
1650
|
+
let limit;
|
|
1651
|
+
if (limitParam !== undefined) {
|
|
1652
|
+
limit = Number(limitParam);
|
|
1653
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 20) {
|
|
1654
|
+
return c.json({ error: 'Session limit must be an integer from 1 to 20.' }, 400);
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1583
1657
|
const config = await loadConfig();
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1658
|
+
const requestedWorkspacePath = resolveWorkspacePath(config.workspacesDir, id);
|
|
1659
|
+
let workspacePath = requestedWorkspacePath;
|
|
1660
|
+
let feature;
|
|
1661
|
+
if (desktopHandoffOnly) {
|
|
1662
|
+
try {
|
|
1663
|
+
const exactWorkspacePath = await resolveExactLaunchWorkspace(config.workspacesDir, requestedWorkspacePath);
|
|
1664
|
+
if (!exactWorkspacePath) {
|
|
1665
|
+
return c.json({ error: 'Workspace configuration not found.' }, 404);
|
|
1666
|
+
}
|
|
1667
|
+
workspacePath = exactWorkspacePath;
|
|
1668
|
+
}
|
|
1669
|
+
catch (error) {
|
|
1670
|
+
if (error instanceof PathAccessError)
|
|
1671
|
+
throw error;
|
|
1672
|
+
return c.json({ error: 'Workspace configuration not found.' }, 404);
|
|
1673
|
+
}
|
|
1674
|
+
feature = await loadWorkspaceManifest(workspacePath);
|
|
1675
|
+
}
|
|
1676
|
+
else {
|
|
1677
|
+
feature = await loadFeatureConfig(workspacePath);
|
|
1678
|
+
}
|
|
1586
1679
|
if (!feature) {
|
|
1587
1680
|
return c.json({ error: 'Workspace configuration not found.' }, 404);
|
|
1588
1681
|
}
|
|
1589
|
-
const
|
|
1682
|
+
const discoveredSessions = await findSessions(workspacePath, feature.repos);
|
|
1683
|
+
if (!desktopHandoffOnly) {
|
|
1684
|
+
return c.json({ sessions: limit === undefined ? discoveredSessions : discoveredSessions.slice(0, limit) });
|
|
1685
|
+
}
|
|
1686
|
+
const requestedCount = limit ?? 3;
|
|
1687
|
+
const candidates = discoveredSessions
|
|
1688
|
+
.filter((session) => session.assistant === 'codex' || session.assistant === 'claude')
|
|
1689
|
+
.slice(0, DESKTOP_HANDOFF_SCAN_LIMIT);
|
|
1690
|
+
const sessions = [];
|
|
1691
|
+
const claudeTransferAvailable = candidates.some((session) => session.assistant === 'claude')
|
|
1692
|
+
&& canOfferClaudeDesktopTransfer();
|
|
1693
|
+
for (const session of candidates) {
|
|
1694
|
+
if (session.assistant === 'codex' && await canOpenCodexSessionInWorkspace(workspacePath, feature.repos, session.id)) {
|
|
1695
|
+
sessions.push({
|
|
1696
|
+
...session,
|
|
1697
|
+
desktopHandoff: { targetId: 'codex-desktop', method: 'direct' },
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
else if (session.assistant === 'claude'
|
|
1701
|
+
&& claudeTransferAvailable
|
|
1702
|
+
&& await canTransferClaudeSessionInWorkspace(workspacePath, feature.repos, session.id)) {
|
|
1703
|
+
sessions.push({
|
|
1704
|
+
...session,
|
|
1705
|
+
desktopHandoff: { targetId: 'claude-desktop', method: 'guided' },
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
if (sessions.length === requestedCount)
|
|
1709
|
+
break;
|
|
1710
|
+
}
|
|
1590
1711
|
return c.json({ sessions });
|
|
1591
1712
|
}
|
|
1592
1713
|
catch (error) {
|
|
@@ -1847,6 +1968,191 @@ and suffix it with:
|
|
|
1847
1968
|
return errorResponse(c, error);
|
|
1848
1969
|
}
|
|
1849
1970
|
});
|
|
1971
|
+
// ─── Skills & Categories Catalog ──────────────────────────────────────────
|
|
1972
|
+
// Get all skill categories (built-in templates + user custom)
|
|
1973
|
+
app.get('/api/skills/categories', async (c) => {
|
|
1974
|
+
try {
|
|
1975
|
+
const categories = await getSkillCategories();
|
|
1976
|
+
return c.json({ categories });
|
|
1977
|
+
}
|
|
1978
|
+
catch (error) {
|
|
1979
|
+
return errorResponse(c, error);
|
|
1980
|
+
}
|
|
1981
|
+
});
|
|
1982
|
+
// Save or update a custom skill category
|
|
1983
|
+
app.post('/api/skills/categories', async (c) => {
|
|
1984
|
+
try {
|
|
1985
|
+
const body = await c.req.json();
|
|
1986
|
+
if (!body.name) {
|
|
1987
|
+
return c.json({ error: 'Category name is required.' }, 400);
|
|
1988
|
+
}
|
|
1989
|
+
const category = await saveSkillCategory(body);
|
|
1990
|
+
return c.json({ success: true, category });
|
|
1991
|
+
}
|
|
1992
|
+
catch (error) {
|
|
1993
|
+
return errorResponse(c, error);
|
|
1994
|
+
}
|
|
1995
|
+
});
|
|
1996
|
+
// Delete a custom skill category
|
|
1997
|
+
app.delete('/api/skills/categories/:id', async (c) => {
|
|
1998
|
+
try {
|
|
1999
|
+
const id = decodeURIComponent(c.req.param('id'));
|
|
2000
|
+
await deleteSkillCategory(id);
|
|
2001
|
+
return c.json({ success: true });
|
|
2002
|
+
}
|
|
2003
|
+
catch (error) {
|
|
2004
|
+
return errorResponse(c, error);
|
|
2005
|
+
}
|
|
2006
|
+
});
|
|
2007
|
+
// Get authoritative skills (built-ins + personal catalog). Workspace
|
|
2008
|
+
// materializations are deliberately never treated as catalog sources.
|
|
2009
|
+
app.get('/api/skills', async (c) => {
|
|
2010
|
+
try {
|
|
2011
|
+
const skills = await getAllSkills();
|
|
2012
|
+
return c.json({ skills });
|
|
2013
|
+
}
|
|
2014
|
+
catch (error) {
|
|
2015
|
+
return errorResponse(c, error);
|
|
2016
|
+
}
|
|
2017
|
+
});
|
|
2018
|
+
// Save or update a custom skill
|
|
2019
|
+
app.post('/api/skills', async (c) => {
|
|
2020
|
+
try {
|
|
2021
|
+
const body = await c.req.json();
|
|
2022
|
+
if (!body.name || !body.content) {
|
|
2023
|
+
return c.json({ error: 'Skill name and content are required.' }, 400);
|
|
2024
|
+
}
|
|
2025
|
+
const skill = await saveSkill(body);
|
|
2026
|
+
return c.json({ success: true, skill });
|
|
2027
|
+
}
|
|
2028
|
+
catch (error) {
|
|
2029
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2030
|
+
return c.json({ error: message }, 400);
|
|
2031
|
+
}
|
|
2032
|
+
});
|
|
2033
|
+
// Delete a custom skill
|
|
2034
|
+
app.delete('/api/skills/:id', async (c) => {
|
|
2035
|
+
try {
|
|
2036
|
+
const id = decodeURIComponent(c.req.param('id'));
|
|
2037
|
+
const config = await loadConfig();
|
|
2038
|
+
const assignments = await withResourceAdministrationLock(async () => {
|
|
2039
|
+
const currentAssignments = await findResourceAssignments(config.workspacesDir, id, 'skill');
|
|
2040
|
+
if (!currentAssignments.length)
|
|
2041
|
+
await deleteSkill(id);
|
|
2042
|
+
return currentAssignments;
|
|
2043
|
+
});
|
|
2044
|
+
if (assignments.length) {
|
|
2045
|
+
return c.json({
|
|
2046
|
+
error: `Unassign the skill from these workspaces before deleting it: ${assignments.join(', ')}`,
|
|
2047
|
+
workspaces: assignments,
|
|
2048
|
+
}, 409);
|
|
2049
|
+
}
|
|
2050
|
+
return c.json({ success: true });
|
|
2051
|
+
}
|
|
2052
|
+
catch (error) {
|
|
2053
|
+
return errorResponse(c, error);
|
|
2054
|
+
}
|
|
2055
|
+
});
|
|
2056
|
+
// Codex-native custom-agent catalog. Other harness agent formats are not
|
|
2057
|
+
// translated because their configuration and permission models are different.
|
|
2058
|
+
app.get('/api/agents', async (c) => {
|
|
2059
|
+
try {
|
|
2060
|
+
return c.json({ agents: await getAllAgents() });
|
|
2061
|
+
}
|
|
2062
|
+
catch (error) {
|
|
2063
|
+
return errorResponse(c, error);
|
|
2064
|
+
}
|
|
2065
|
+
});
|
|
2066
|
+
app.post('/api/agents', async (c) => {
|
|
2067
|
+
try {
|
|
2068
|
+
const agent = await saveAgent(await c.req.json());
|
|
2069
|
+
return c.json({ success: true, agent });
|
|
2070
|
+
}
|
|
2071
|
+
catch (error) {
|
|
2072
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2073
|
+
return c.json({ error: message }, 400);
|
|
2074
|
+
}
|
|
2075
|
+
});
|
|
2076
|
+
app.post('/api/agents/import', async (c) => {
|
|
2077
|
+
try {
|
|
2078
|
+
const body = await c.req.json();
|
|
2079
|
+
if (typeof body.toml !== 'string') {
|
|
2080
|
+
return c.json({ error: 'A TOML string is required.' }, 400);
|
|
2081
|
+
}
|
|
2082
|
+
const agent = await importAgentToml(body.toml, typeof body.category === 'string' ? body.category : 'general');
|
|
2083
|
+
return c.json({ success: true, agent });
|
|
2084
|
+
}
|
|
2085
|
+
catch (error) {
|
|
2086
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2087
|
+
return c.json({ error: message }, 400);
|
|
2088
|
+
}
|
|
2089
|
+
});
|
|
2090
|
+
app.delete('/api/agents/:id', async (c) => {
|
|
2091
|
+
try {
|
|
2092
|
+
const id = decodeURIComponent(c.req.param('id'));
|
|
2093
|
+
const config = await loadConfig();
|
|
2094
|
+
const assignments = await withResourceAdministrationLock(async () => {
|
|
2095
|
+
const currentAssignments = await findResourceAssignments(config.workspacesDir, id, 'agent');
|
|
2096
|
+
if (!currentAssignments.length)
|
|
2097
|
+
await deleteAgent(id);
|
|
2098
|
+
return currentAssignments;
|
|
2099
|
+
});
|
|
2100
|
+
if (assignments.length) {
|
|
2101
|
+
return c.json({
|
|
2102
|
+
error: `Unassign the agent from these workspaces before deleting it: ${assignments.join(', ')}`,
|
|
2103
|
+
workspaces: assignments,
|
|
2104
|
+
}, 409);
|
|
2105
|
+
}
|
|
2106
|
+
return c.json({ success: true });
|
|
2107
|
+
}
|
|
2108
|
+
catch (error) {
|
|
2109
|
+
return errorResponse(c, error);
|
|
2110
|
+
}
|
|
2111
|
+
});
|
|
2112
|
+
// Get workspace skills assignment config
|
|
2113
|
+
app.get('/api/skills/workspace/:id', async (c) => {
|
|
2114
|
+
try {
|
|
2115
|
+
const id = decodeURIComponent(c.req.param('id'));
|
|
2116
|
+
const config = await loadConfig();
|
|
2117
|
+
const wsPath = await resolveExactWorkspaceById(config.workspacesDir, id);
|
|
2118
|
+
if (!wsPath)
|
|
2119
|
+
return c.json({ error: 'Workspace not found.' }, 404);
|
|
2120
|
+
const skillsConfig = await getWorkspaceSkillsConfig(wsPath);
|
|
2121
|
+
return c.json({ config: skillsConfig });
|
|
2122
|
+
}
|
|
2123
|
+
catch (error) {
|
|
2124
|
+
return errorResponse(c, error);
|
|
2125
|
+
}
|
|
2126
|
+
});
|
|
2127
|
+
// Save workspace skills assignment config
|
|
2128
|
+
app.post('/api/skills/workspace/:id/assign', async (c) => {
|
|
2129
|
+
try {
|
|
2130
|
+
const id = decodeURIComponent(c.req.param('id'));
|
|
2131
|
+
const body = await c.req.json();
|
|
2132
|
+
if (!Array.isArray(body.enabledSkills) || !Array.isArray(body.enabledAgents)) {
|
|
2133
|
+
return c.json({ error: 'enabledSkills and enabledAgents arrays are required.' }, 400);
|
|
2134
|
+
}
|
|
2135
|
+
if (!Number.isInteger(body.expectedRevision) || body.expectedRevision < 0) {
|
|
2136
|
+
return c.json({ error: 'A nonnegative integer expectedRevision is required.' }, 400);
|
|
2137
|
+
}
|
|
2138
|
+
const config = await loadConfig();
|
|
2139
|
+
const wsPath = await resolveExactWorkspaceById(config.workspacesDir, id);
|
|
2140
|
+
if (!wsPath)
|
|
2141
|
+
return c.json({ error: 'Workspace not found.' }, 404);
|
|
2142
|
+
const saved = await withResourceAdministrationLock(async () => {
|
|
2143
|
+
await validateResourceSelections(body.enabledSkills, body.enabledAgents);
|
|
2144
|
+
return saveWorkspaceSkillsConfig(wsPath, {
|
|
2145
|
+
enabledSkills: body.enabledSkills,
|
|
2146
|
+
enabledAgents: body.enabledAgents,
|
|
2147
|
+
enabledCategories: Array.isArray(body.enabledCategories) ? body.enabledCategories : [],
|
|
2148
|
+
}, body.expectedRevision);
|
|
2149
|
+
});
|
|
2150
|
+
return c.json({ success: true, config: saved });
|
|
2151
|
+
}
|
|
2152
|
+
catch (error) {
|
|
2153
|
+
return errorResponse(c, error);
|
|
2154
|
+
}
|
|
2155
|
+
});
|
|
1850
2156
|
// ─── Schedules: recurring workspace jobs (sync/refresh) ─────────────────
|
|
1851
2157
|
// List all scheduled jobs (with computed next-due time)
|
|
1852
2158
|
app.get('/api/schedules', async (c) => {
|