Skip to content

Commit b131599

Browse files
committed
refactor: migrate from syncpoint-core to syncpoint-adapters, syncpoint-kernel, and syncpoint-context
- Updated imports across multiple repositories to replace syncpoint-core with syncpoint-adapters, syncpoint-kernel, and syncpoint-context. - Adjusted type imports accordingly to reflect the new structure. - Modified tsconfig.json files to include new path mappings for the updated packages. - Ensured all references in tests and routers are aligned with the new package structure.
1 parent 3b73144 commit b131599

203 files changed

Lines changed: 9896 additions & 411 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "syncpoint-adapters",
3+
"version": "0.1.0",
4+
"description": "SyncPoint adapters/orchestration layer — external integration surfaces",
5+
"type": "module",
6+
"main": "dist/index.js",
7+
"types": "dist/index.d.ts",
8+
"files": ["dist"],
9+
"exports": {
10+
".": {
11+
"source": "./src/index.ts",
12+
"types": "./dist/index.d.ts",
13+
"import": "./dist/index.js"
14+
}
15+
},
16+
"scripts": {
17+
"build": "tsc -p tsconfig.json",
18+
"typecheck": "tsc --noEmit"
19+
},
20+
"dependencies": {
21+
"syncpoint-kernel": "workspace:*",
22+
"syncpoint-governance": "workspace:*",
23+
"syncpoint-context": "workspace:*",
24+
"yaml": "^2.4.2",
25+
"zod": "^3.23.0"
26+
},
27+
"devDependencies": {
28+
"typescript": "^5.5.0"
29+
}
30+
}
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/**
2+
* Agent Adapter Protocol — standardized interface for AI editor integration.
3+
*
4+
* Each adapter defines how a specific AI editor (Codex, Claude Code, Cursor, Cline)
5+
* should consume SyncPoint's resume context at key lifecycle moments:
6+
*
7+
* onBoot — agent starts fresh or is assigned a task
8+
* onResume — agent resumes after pause / context switch
9+
* onHandoff — agent receives a task handoff from another agent
10+
*
11+
* The adapter protocol does NOT control the editor directly.
12+
* It produces the correct files and instructions so that the editor's native
13+
* mechanism picks up the narrowed context.
14+
*/
15+
16+
import { z } from "zod";
17+
import type { ResumeContext } from "syncpoint-context";
18+
import type { PromptFormat } from "syncpoint-context";
19+
20+
// ── Provider enum ────────────────────────────────────
21+
22+
export const AgentProvider = z.enum([
23+
"codex",
24+
"claude-code",
25+
"cursor",
26+
"cline",
27+
"copilot",
28+
"human",
29+
"other",
30+
]);
31+
export type AgentProvider = z.infer<typeof AgentProvider>;
32+
33+
// ── Lifecycle events ─────────────────────────────────
34+
35+
export const AdapterLifecycleEvent = z.enum([
36+
"boot",
37+
"resume",
38+
"handoff",
39+
"checkpoint",
40+
]);
41+
export type AdapterLifecycleEvent = z.infer<typeof AdapterLifecycleEvent>;
42+
43+
// ── Adapter instruction ──────────────────────────────
44+
45+
export const AdapterInstructionSchema = z.object({
46+
/** Lifecycle event that triggered this instruction */
47+
event: AdapterLifecycleEvent,
48+
/** Provider this instruction targets */
49+
provider: AgentProvider,
50+
/** Files to write (relative path → content) */
51+
files: z.record(z.string()),
52+
/** Formatted prompt text for clipboard / system prompt injection */
53+
promptText: z.string(),
54+
/** Format used for the primary rules file */
55+
primaryFormat: z.string(),
56+
/** Human-readable summary of what the adapter did */
57+
summary: z.string(),
58+
/** Warnings from resume context */
59+
warnings: z.array(z.string()),
60+
/** Whether the context is ready */
61+
ready: z.boolean(),
62+
});
63+
64+
export type AdapterInstruction = z.infer<typeof AdapterInstructionSchema>;
65+
66+
// ── Adapter config per provider ──────────────────────
67+
68+
export interface AdapterConfig {
69+
/** Which provider this adapter serves */
70+
provider: AgentProvider;
71+
/** Primary rules file format */
72+
rulesFormat: PromptFormat;
73+
/** File path for the primary rules file (relative to project root) */
74+
rulesFile: string;
75+
/** Additional files to generate */
76+
extraFiles: { path: string; format: PromptFormat }[];
77+
/** System prompt preamble injected before resume context */
78+
preamble: string;
79+
/** Instructions shown to the user about how to configure the editor */
80+
setupInstructions: string;
81+
}
82+
83+
// ── Built-in adapter configs ─────────────────────────
84+
85+
export const ADAPTER_CONFIGS: Record<string, AdapterConfig> = {
86+
cursor: {
87+
provider: "cursor",
88+
rulesFormat: "cursorrules",
89+
rulesFile: ".cursorrules",
90+
extraFiles: [],
91+
preamble:
92+
"You are working on a SyncPoint-managed project. " +
93+
"The rules below are your ONLY source of task context. " +
94+
"Do NOT use previous conversation history.",
95+
setupInstructions:
96+
"Cursor reads .cursorrules automatically from the project root.\n" +
97+
"Run `syncpoint adapter boot` after each resume or handoff.\n" +
98+
"The .cursorrules file will be overwritten with the latest context.",
99+
},
100+
101+
"claude-code": {
102+
provider: "claude-code",
103+
rulesFormat: "agents-md",
104+
rulesFile: "AGENTS.md",
105+
extraFiles: [
106+
{ path: ".syncpoint/resume-prompt.md", format: "system-prompt" },
107+
],
108+
preamble:
109+
"You are working on a SyncPoint-managed project. " +
110+
"Read AGENTS.md for your current task context. " +
111+
"Do NOT carry over previous conversation history.",
112+
setupInstructions:
113+
"Claude Code reads AGENTS.md as project knowledge.\n" +
114+
"Run `syncpoint adapter boot` after each resume or handoff.\n" +
115+
"Start new conversations with: /read AGENTS.md",
116+
},
117+
118+
codex: {
119+
provider: "codex",
120+
rulesFormat: "agents-md",
121+
rulesFile: "AGENTS.md",
122+
extraFiles: [
123+
{ path: ".syncpoint/resume-prompt.md", format: "system-prompt" },
124+
],
125+
preamble:
126+
"You are working on a SyncPoint-managed project. " +
127+
"Read AGENTS.md for your current task context. " +
128+
"Do NOT carry over previous conversation history.",
129+
setupInstructions:
130+
"Codex reads AGENTS.md as project context.\n" +
131+
"Run `syncpoint adapter boot` after each resume or handoff.\n" +
132+
"Pass --system-prompt from .syncpoint/resume-prompt.md when using API.",
133+
},
134+
135+
cline: {
136+
provider: "cline",
137+
rulesFormat: "system-prompt",
138+
rulesFile: ".syncpoint/resume-prompt.md",
139+
extraFiles: [
140+
{ path: ".cursorrules", format: "cursorrules" },
141+
],
142+
preamble:
143+
"You are working on a SyncPoint-managed project. " +
144+
"The system prompt below is your ONLY source of task context. " +
145+
"Do NOT use previous conversation history.",
146+
setupInstructions:
147+
"Cline uses system prompts from its settings.\n" +
148+
"Run `syncpoint adapter boot` after each resume or handoff.\n" +
149+
"Copy .syncpoint/resume-prompt.md into Cline's custom system prompt field.",
150+
},
151+
152+
copilot: {
153+
provider: "copilot",
154+
rulesFormat: "agents-md",
155+
rulesFile: "AGENTS.md",
156+
extraFiles: [],
157+
preamble:
158+
"You are working on a SyncPoint-managed project. " +
159+
"Read AGENTS.md for context.",
160+
setupInstructions:
161+
"GitHub Copilot reads AGENTS.md for project context.\n" +
162+
"Run `syncpoint adapter boot` after each resume or handoff.",
163+
},
164+
};
165+
166+
// ── Build adapter instruction ────────────────────────
167+
168+
import { formatResumePrompt } from "syncpoint-context";
169+
import type { RealityProjection } from "syncpoint-context";
170+
171+
/**
172+
* Build an AdapterInstruction for a given provider and lifecycle event.
173+
* This produces the file contents and prompt text that should be written
174+
* to the project directory so the editor picks up the narrowed context.
175+
*/
176+
export function buildAdapterInstruction(
177+
ctx: ResumeContext,
178+
provider: AgentProvider,
179+
event: AdapterLifecycleEvent = "resume",
180+
projection?: RealityProjection | null,
181+
): AdapterInstruction {
182+
const config = ADAPTER_CONFIGS[provider] ?? ADAPTER_CONFIGS["cursor"]!;
183+
184+
const files: Record<string, string> = {};
185+
186+
// Primary rules file — P2: pass projection to all formats
187+
const primaryContent = formatResumePrompt(ctx, config.rulesFormat, projection);
188+
files[config.rulesFile] = primaryContent;
189+
190+
// Extra files
191+
for (const extra of config.extraFiles) {
192+
files[extra.path] = formatResumePrompt(ctx, extra.format, projection);
193+
}
194+
195+
// Prompt text for clipboard / API injection
196+
const promptText = config.preamble + "\n\n" + formatResumePrompt(ctx, "system-prompt", projection);
197+
198+
const fileList = Object.keys(files).join(", ");
199+
const summary = `[${event}] ${config.provider}: wrote ${fileList}`;
200+
201+
return {
202+
event,
203+
provider: config.provider,
204+
files,
205+
promptText,
206+
primaryFormat: config.rulesFormat,
207+
summary,
208+
warnings: ctx.warnings,
209+
ready: ctx.ready,
210+
};
211+
}
212+
213+
/**
214+
* Get adapter config for a provider. Returns undefined if not found.
215+
*/
216+
export function getAdapterConfig(provider: string): AdapterConfig | undefined {
217+
return ADAPTER_CONFIGS[provider];
218+
}
219+
220+
/**
221+
* List all known adapter provider names.
222+
*/
223+
export function listAdapterProviders(): string[] {
224+
return Object.keys(ADAPTER_CONFIGS);
225+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { z } from "zod";
2+
import { AgentStatus } from "./states.js";
3+
import { AgentCapabilitySchema, AgentAvailability } from "./agent-manifest.js";
4+
import type { AgentManifest } from "./agent-manifest.js";
5+
import { AgentRoleSchema, UserAgentProviderSchema } from "./agent-file-manifest.js";
6+
import type { UserAgentManifest } from "./agent-file-manifest.js";
7+
import type { Agent } from "./models.js";
8+
import { toUserAgentManifestFromRuntime } from "./agent-manifest-conversion.js";
9+
10+
export const AgentCardEndpointSchema = z.object({
11+
kind: z.string().min(1),
12+
url: z.string().min(1),
13+
});
14+
15+
export type AgentCardEndpoint = z.infer<typeof AgentCardEndpointSchema>;
16+
17+
export const AgentCardSchema = z.object({
18+
schema: z.literal("syncpoint/agent-card/v1"),
19+
agentId: z.string().nullable().default(null),
20+
manifestPath: z.string().nullable().default(null),
21+
name: z.string().min(1),
22+
profile: z.string().min(1),
23+
role: AgentRoleSchema,
24+
provider: UserAgentProviderSchema,
25+
status: z.nativeEnum(AgentStatus).nullable().default(null),
26+
availability: z.nativeEnum(AgentAvailability).default(AgentAvailability.ONLINE),
27+
tags: z.array(z.string()).default([]),
28+
capabilities: z.array(AgentCapabilitySchema).default([]),
29+
notes: z.string().default(""),
30+
canHandleHumanEscalation: z.boolean().default(false),
31+
protocols: z.array(z.string()).default(["syncpoint", "a2a-like"]),
32+
endpoints: z.array(AgentCardEndpointSchema).default([]),
33+
metadata: z.record(z.string()).default({}),
34+
});
35+
36+
export type AgentCard = z.infer<typeof AgentCardSchema>;
37+
38+
type AgentCardRuntimeManifestSource = Partial<
39+
Pick<
40+
AgentManifest,
41+
"capabilities" | "escalationPreference" | "availability" | "canHandleHumanEscalation" | "tags"
42+
>
43+
>;
44+
45+
export interface BuildAgentCardInput {
46+
manifestPath?: string | null;
47+
agent?: Pick<Agent, "id" | "name" | "provider" | "role" | "status"> | null;
48+
declaredManifest?: UserAgentManifest | null;
49+
runtimeManifest?: AgentCardRuntimeManifestSource | null;
50+
endpoints?: AgentCardEndpoint[];
51+
metadata?: Record<string, string>;
52+
}
53+
54+
export function buildAgentCard(input: BuildAgentCardInput): AgentCard {
55+
const manifest = resolveCardManifest(input);
56+
if (!manifest) {
57+
throw new Error("Cannot build agent card without a declared or derived manifest.");
58+
}
59+
60+
return AgentCardSchema.parse({
61+
schema: "syncpoint/agent-card/v1",
62+
agentId: input.agent?.id ?? null,
63+
manifestPath: input.manifestPath ?? null,
64+
name: manifest.name,
65+
profile: manifest.profile,
66+
role: manifest.role,
67+
provider: manifest.provider,
68+
status: input.agent?.status ?? null,
69+
availability: manifest.availability,
70+
tags: manifest.tags,
71+
capabilities: manifest.capabilities,
72+
notes: manifest.notes,
73+
canHandleHumanEscalation: manifest.canHandleHumanEscalation,
74+
protocols: ["syncpoint", "a2a-like"],
75+
endpoints: input.endpoints ?? [],
76+
metadata: {
77+
source: input.declaredManifest ? "declared" : "runtime-derived",
78+
...(input.metadata ?? {}),
79+
},
80+
});
81+
}
82+
83+
function resolveCardManifest(input: BuildAgentCardInput): UserAgentManifest | null {
84+
if (input.declaredManifest) return input.declaredManifest;
85+
if (!input.agent) return null;
86+
return toUserAgentManifestFromRuntime({
87+
agent: input.agent,
88+
runtimeManifest: input.runtimeManifest,
89+
});
90+
}

0 commit comments

Comments
 (0)