@cursor/july 0.1.103 → 0.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channels/change-monitors/change-monitors-channel.d.ts +5 -0
- package/dist/channels/change-monitors/change-monitors-channel.d.ts.map +1 -0
- package/dist/channels/change-monitors/change-monitors-channel.js +41 -0
- package/dist/channels/change-monitors/index.d.ts +4 -0
- package/dist/channels/change-monitors/index.d.ts.map +1 -0
- package/dist/channels/change-monitors/index.js +2 -0
- package/dist/channels/change-monitors/types.d.ts +39 -0
- package/dist/channels/change-monitors/types.d.ts.map +1 -0
- package/dist/channels/change-monitors/types.js +1 -0
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +1 -0
- package/dist/channels/deployments/types.d.ts +2 -0
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +4 -0
- package/dist/channels/github/progress.d.ts +22 -0
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/github/progress.js +32 -5
- package/dist/channels/issues/index.d.ts +4 -0
- package/dist/channels/issues/index.d.ts.map +1 -0
- package/dist/channels/issues/index.js +2 -0
- package/dist/channels/issues/issues-channel.d.ts +5 -0
- package/dist/channels/issues/issues-channel.d.ts.map +1 -0
- package/dist/channels/issues/issues-channel.js +37 -0
- package/dist/channels/issues/types.d.ts +33 -0
- package/dist/channels/issues/types.d.ts.map +1 -0
- package/dist/channels/issues/types.js +1 -0
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.DW9pXkpL.js → app.BVwaffdK.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.CJxMklAy.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CdEIUwDg.js → VPLocalSearchBox.WuWTZ1x8.js} +1 -1
- package/dist/docs/assets/chunks/{theme.YZMHgPgg.js → theme.BYdI_6sF.js} +2 -2
- package/dist/docs/assets/{guides_github.md.DKYiT9do.js → guides_github.md.c0gdGJ-D.js} +1 -1
- package/dist/docs/assets/{guides_github.md.DKYiT9do.lean.js → guides_github.md.c0gdGJ-D.lean.js} +1 -1
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.js +9 -0
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.lean.js +1 -0
- package/dist/docs/assets/index.md.BW_6tOgR.js +5 -0
- package/dist/docs/assets/index.md.BW_6tOgR.lean.js +1 -0
- package/dist/docs/assets/{reference_channels.md.Dz8Cnudp.js → reference_channels.md.DBGcaB7m.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.Dz8Cnudp.lean.js → reference_channels.md.DBGcaB7m.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CJNc_xYK.js → reference_cli.md.C6Lo8SEd.js} +2 -1
- package/dist/docs/assets/{reference_extensions.md.DykHW3qL.js → reference_extensions.md.CGmMLblt.js} +1 -1
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.js +3 -0
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.lean.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/design/filesystem.md +376 -0
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-agents.html +5 -5
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +6 -6
- package/dist/docs/guides/github.md +5 -0
- package/dist/docs/guides/grokbot-agents.html +35 -0
- package/dist/docs/guides/grokbot-agents.md +88 -0
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +5 -5
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +6 -1
- package/dist/docs/llms-full.txt +562 -2
- package/dist/docs/llms.txt +3 -0
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +6 -6
- package/dist/docs/reference/channels.md +20 -0
- package/dist/docs/reference/cli.html +7 -6
- package/dist/docs/reference/cli.md +2 -1
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/extensions.html +6 -6
- package/dist/docs/reference/extensions.md +2 -0
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/result.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/skills/ab.html +4 -4
- package/dist/docs/skills/create-agent.html +4 -4
- package/dist/docs/skills/debug.html +4 -4
- package/dist/docs/skills/evals.html +4 -4
- package/dist/docs/skills/framework-map.html +4 -4
- package/dist/docs/skills/github.html +4 -4
- package/dist/docs/skills/hillclimb.html +4 -4
- package/dist/docs/skills/index.html +4 -4
- package/dist/docs/skills/mcp-auth.html +4 -4
- package/dist/docs/skills/otel.html +4 -4
- package/dist/docs/skills/setup-slack.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +5 -5
- package/dist/docs/templates/demo.html +5 -5
- package/dist/docs/templates/grokbot-agents.html +29 -0
- package/dist/docs/templates/grokbot-agents.md +48 -0
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/files.d.ts +7 -2
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +7 -2
- package/dist/filesystem.d.ts +440 -0
- package/dist/filesystem.d.ts.map +1 -0
- package/dist/filesystem.js +1694 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/continuation-channel.d.ts +4 -2
- package/dist/internal/continuation-channel.d.ts.map +1 -1
- package/dist/internal/continuation-channel.js +21 -12
- package/dist/internal/continuation-identity.d.ts +13 -5
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +74 -35
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +80 -8
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +3 -0
- package/dist/internal/factory-resource-channel.d.ts +33 -0
- package/dist/internal/factory-resource-channel.d.ts.map +1 -0
- package/dist/internal/factory-resource-channel.js +77 -0
- package/dist/internal/filesystem/errors.d.ts +64 -0
- package/dist/internal/filesystem/errors.d.ts.map +1 -0
- package/dist/internal/filesystem/errors.js +175 -0
- package/dist/internal/filesystem/format.d.ts +28 -0
- package/dist/internal/filesystem/format.d.ts.map +1 -0
- package/dist/internal/filesystem/format.js +213 -0
- package/dist/internal/filesystem/merge.d.ts +34 -0
- package/dist/internal/filesystem/merge.d.ts.map +1 -0
- package/dist/internal/filesystem/merge.js +196 -0
- package/dist/internal/filesystem/scratch.d.ts +59 -0
- package/dist/internal/filesystem/scratch.d.ts.map +1 -0
- package/dist/internal/filesystem/scratch.js +212 -0
- package/dist/internal/filesystem/sdk-schemas.d.ts +29 -0
- package/dist/internal/filesystem/sdk-schemas.d.ts.map +1 -0
- package/dist/internal/filesystem/sdk-schemas.js +153 -0
- package/dist/internal/filesystem/tools.d.ts +42 -0
- package/dist/internal/filesystem/tools.d.ts.map +1 -0
- package/dist/internal/filesystem/tools.js +618 -0
- package/dist/internal/filesystem/walk.d.ts +74 -0
- package/dist/internal/filesystem/walk.d.ts.map +1 -0
- package/dist/internal/filesystem/walk.js +339 -0
- package/dist/internal/framework-file-storage.d.ts +3 -1
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +3 -1
- package/dist/internal/guest-network.d.ts +5 -2
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +7 -2
- package/dist/internal/hosted-delivery.d.ts +7 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +41 -3
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -1
- package/dist/internal/hosted-managed-automation.js +27 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +4 -1
- package/dist/internal/sdk-runner.d.ts +13 -1
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +21 -1
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +11 -3
- package/dist/internal/session-engine.d.ts +30 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +484 -82
- package/dist/internal/store-mirror.d.ts +2 -2
- package/dist/internal/store-mirror.js +2 -2
- package/dist/internal/tenant-slack/relay.d.ts +2 -0
- package/dist/internal/tenant-slack/relay.d.ts.map +1 -1
- package/dist/internal/tenant-slack/relay.js +18 -8
- package/dist/internal/testing/factory-resource-fixtures.d.ts +48 -0
- package/dist/internal/testing/factory-resource-fixtures.d.ts.map +1 -0
- package/dist/internal/testing/factory-resource-fixtures.js +41 -0
- package/dist/internal/workspace-sync.d.ts +31 -6
- package/dist/internal/workspace-sync.d.ts.map +1 -1
- package/dist/internal/workspace-sync.js +67 -12
- package/dist/internal/workspace.d.ts +9 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +16 -0
- package/dist/playground/assets/{index-59KvgREd.js → index-BaQzjaNK.js} +40 -40
- package/dist/playground/assets/index-CceqnLTX.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +60 -11
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +6 -1
- package/docs/design/filesystem.md +376 -0
- package/docs/guides/github.md +5 -0
- package/docs/guides/grokbot-agents.md +93 -0
- package/docs/reference/channels.md +20 -0
- package/docs/reference/cli.md +2 -1
- package/docs/reference/extensions.md +2 -0
- package/docs/templates/grokbot-agents.md +53 -0
- package/package.json +25 -2
- package/src/channels/change-monitors/change-monitors-channel.ts +62 -0
- package/src/channels/change-monitors/index.ts +8 -0
- package/src/channels/change-monitors/types.ts +44 -0
- package/src/channels/deployments/deployments-channel.ts +1 -0
- package/src/channels/deployments/types.ts +2 -0
- package/src/channels/github/defaults.ts +4 -0
- package/src/channels/github/progress.ts +76 -10
- package/src/channels/issues/index.ts +9 -0
- package/src/channels/issues/issues-channel.ts +51 -0
- package/src/channels/issues/types.ts +41 -0
- package/src/files.ts +9 -2
- package/src/filesystem.ts +2074 -0
- package/src/index.ts +28 -0
- package/src/internal/continuation-channel.ts +29 -12
- package/src/internal/continuation-identity.ts +122 -37
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/discovery/agent.ts +87 -1
- package/src/internal/discovery/info.ts +3 -0
- package/src/internal/factory-resource-channel.ts +122 -0
- package/src/internal/filesystem/errors.ts +220 -0
- package/src/internal/filesystem/format.ts +276 -0
- package/src/internal/filesystem/merge.ts +195 -0
- package/src/internal/filesystem/scratch.ts +255 -0
- package/src/internal/filesystem/sdk-schemas.ts +204 -0
- package/src/internal/filesystem/tools.ts +821 -0
- package/src/internal/filesystem/walk.ts +369 -0
- package/src/internal/framework-file-storage.ts +3 -1
- package/src/internal/guest-network.ts +8 -2
- package/src/internal/hosted-delivery.ts +71 -2
- package/src/internal/hosted-managed-automation.ts +49 -5
- package/src/internal/init-project.ts +4 -1
- package/src/internal/sdk-runner.ts +23 -0
- package/src/internal/server.ts +16 -0
- package/src/internal/session-engine.ts +595 -73
- package/src/internal/store-mirror.ts +2 -2
- package/src/internal/tenant-slack/relay.ts +28 -4
- package/src/internal/testing/factory-resource-fixtures.ts +85 -0
- package/src/internal/workspace-sync.ts +84 -12
- package/src/internal/workspace.ts +20 -0
- package/src/types.ts +58 -11
- package/templates/grokbot-agents/README.md +26 -0
- package/templates/grokbot-agents/agent/agent.ts +6 -0
- package/templates/grokbot-agents/agent/extensions/grokbot.ts +5 -0
- package/templates/grokbot-agents/agent/instructions.md +7 -0
- package/templates/grokbot-agents/evals/evals.config.ts +5 -0
- package/templates/grokbot-agents/evals/grokbot-agents.eval.ts +18 -0
- package/templates/grokbot-agents/init.json +18 -0
- package/templates/grokbot-agents/package.json +17 -0
- package/templates/grokbot-agents/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.nrl1ifBq.js +0 -1
- package/dist/docs/assets/index.md.D75GWhPl.js +0 -5
- package/dist/docs/assets/index.md.D75GWhPl.lean.js +0 -1
- package/dist/playground/assets/index-MbMxXg-y.css +0 -1
- /package/dist/docs/assets/{reference_cli.md.CJNc_xYK.lean.js → reference_cli.md.C6Lo8SEd.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.DykHW3qL.lean.js → reference_extensions.md.CGmMLblt.lean.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Mirror an authored file tree onto an Agent Store prefix. Shared by the
|
|
3
|
-
* skills
|
|
4
|
-
* discipline and the same path refusals.
|
|
3
|
+
* skills, workspace seed, and session workspaceFile syncs so they keep the
|
|
4
|
+
* same write-then-sweep discipline and the same path refusals.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { posix } from "node:path";
|
|
@@ -109,13 +109,22 @@ export async function postRelaySlackMessage(args: {
|
|
|
109
109
|
resolve?: () => RelaySlackPostTarget | undefined;
|
|
110
110
|
fetchImpl?: typeof fetch;
|
|
111
111
|
timeoutMs?: number;
|
|
112
|
+
/** Diagnostic sink; defaults to `console.info`. */
|
|
113
|
+
log?: (line: string) => void;
|
|
112
114
|
}): Promise<RelaySlackPostResult> {
|
|
113
115
|
const channel = args.channel.trim();
|
|
116
|
+
const log = args.log ?? ((line: string) => console.info(line));
|
|
114
117
|
if (channel === "") {
|
|
118
|
+
log(
|
|
119
|
+
`[agent-sdk-slack-relay-client] refusing post automationUuid=${args.automationUuid}: empty channel`
|
|
120
|
+
);
|
|
115
121
|
return { ok: false, channel, status: 0, error: "empty channel" };
|
|
116
122
|
}
|
|
117
123
|
const target = (args.resolve ?? resolveRelaySlackTarget)();
|
|
118
124
|
if (target === undefined) {
|
|
125
|
+
log(
|
|
126
|
+
`[agent-sdk-slack-relay-client] refusing post automationUuid=${args.automationUuid} channel=${channel}: no Cursor credential resolved (CURSOR_API_KEY / pod credential absent)`
|
|
127
|
+
);
|
|
119
128
|
return {
|
|
120
129
|
ok: false,
|
|
121
130
|
channel,
|
|
@@ -128,6 +137,11 @@ export async function postRelaySlackMessage(args: {
|
|
|
128
137
|
baseUrl: target.relayBaseUrl,
|
|
129
138
|
automationUuid: args.automationUuid,
|
|
130
139
|
});
|
|
140
|
+
const messageChars = args.message.length;
|
|
141
|
+
log(
|
|
142
|
+
`[agent-sdk-slack-relay-client] POST ${url} channel=${channel} messageChars=${String(messageChars)} truncated=${String(messageChars > AGENT_SDK_SLACK_RELAY_MAX_MESSAGE_CHARS)} threaded=${String(args.threadTs !== undefined)} timeoutMs=${String(args.timeoutMs ?? DEFAULT_TIMEOUT_MS)}`
|
|
143
|
+
);
|
|
144
|
+
const startedAt = Date.now();
|
|
131
145
|
let response: Response;
|
|
132
146
|
try {
|
|
133
147
|
response = await fetchImpl(url, {
|
|
@@ -145,6 +159,9 @@ export async function postRelaySlackMessage(args: {
|
|
|
145
159
|
signal: AbortSignal.timeout(args.timeoutMs ?? DEFAULT_TIMEOUT_MS),
|
|
146
160
|
});
|
|
147
161
|
} catch (error) {
|
|
162
|
+
log(
|
|
163
|
+
`[agent-sdk-slack-relay-client] request failed before a response channel=${channel} automationUuid=${args.automationUuid} elapsedMs=${String(Date.now() - startedAt)}: ${describeError(error)}`
|
|
164
|
+
);
|
|
148
165
|
return { ok: false, channel, status: 0, error: describeError(error) };
|
|
149
166
|
}
|
|
150
167
|
let body: unknown;
|
|
@@ -158,16 +175,23 @@ export async function postRelaySlackMessage(args: {
|
|
|
158
175
|
? (body as Record<string, unknown>)
|
|
159
176
|
: {};
|
|
160
177
|
if (!response.ok || record.ok !== true) {
|
|
178
|
+
const error =
|
|
179
|
+
typeof record.error === "string" && record.error !== ""
|
|
180
|
+
? record.error
|
|
181
|
+
: `relay responded ${response.status}`;
|
|
182
|
+
log(
|
|
183
|
+
`[agent-sdk-slack-relay-client] relay denied channel=${channel} automationUuid=${args.automationUuid} status=${String(response.status)} bodyOk=${String(record.ok)} elapsedMs=${String(Date.now() - startedAt)}: ${error}`
|
|
184
|
+
);
|
|
161
185
|
return {
|
|
162
186
|
ok: false,
|
|
163
187
|
channel,
|
|
164
188
|
status: response.status,
|
|
165
|
-
error
|
|
166
|
-
typeof record.error === "string" && record.error !== ""
|
|
167
|
-
? record.error
|
|
168
|
-
: `relay responded ${response.status}`,
|
|
189
|
+
error,
|
|
169
190
|
};
|
|
170
191
|
}
|
|
192
|
+
log(
|
|
193
|
+
`[agent-sdk-slack-relay-client] relay posted channel=${typeof record.channel === "string" ? record.channel : channel} automationUuid=${args.automationUuid} status=${String(response.status)} ts=${typeof record.ts === "string" ? record.ts : "<none>"} elapsedMs=${String(Date.now() - startedAt)}`
|
|
194
|
+
);
|
|
171
195
|
return {
|
|
172
196
|
ok: true,
|
|
173
197
|
channel: typeof record.channel === "string" ? record.channel : channel,
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory resource continuation fixtures shared by July and the control
|
|
3
|
+
* plane identity suite. Pure data: no imports, so server-shared can load
|
|
4
|
+
* this file by relative path without pulling `@cursor/july`.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const FACTORY_CHECKPOINT_NAME: string =
|
|
8
|
+
"changeMonitors/cm-1/checkpoints/cp-1";
|
|
9
|
+
export const FACTORY_ISSUE_NAME: string = "issues/iss-1";
|
|
10
|
+
|
|
11
|
+
export interface FactoryCheckpointResourceFixture {
|
|
12
|
+
name: string;
|
|
13
|
+
deployment: string;
|
|
14
|
+
runKey: string;
|
|
15
|
+
issues: { title: string };
|
|
16
|
+
evidenceSummary: string;
|
|
17
|
+
planRevision: string;
|
|
18
|
+
createTime: string;
|
|
19
|
+
description: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface FactoryIssueResourceFixture {
|
|
23
|
+
name: string;
|
|
24
|
+
title: string;
|
|
25
|
+
body: string;
|
|
26
|
+
state: "STATE_OPEN";
|
|
27
|
+
createTime: string;
|
|
28
|
+
updateTime: string;
|
|
29
|
+
path: string;
|
|
30
|
+
etag: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface CheckpointCreatedPayloadFixture {
|
|
34
|
+
eventId: string;
|
|
35
|
+
eventType: "checkpoint.created";
|
|
36
|
+
teamId: string;
|
|
37
|
+
occurredAtMs: number;
|
|
38
|
+
checkpoint: FactoryCheckpointResourceFixture;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface IssueCreatedPayloadFixture {
|
|
42
|
+
eventId: string;
|
|
43
|
+
eventType: "issue.created";
|
|
44
|
+
teamId: string;
|
|
45
|
+
occurredAtMs: number;
|
|
46
|
+
issue: FactoryIssueResourceFixture;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const FACTORY_CHECKPOINT_RESOURCE: FactoryCheckpointResourceFixture = {
|
|
50
|
+
name: FACTORY_CHECKPOINT_NAME,
|
|
51
|
+
deployment: "deployments/11111111-1111-4111-8111-111111111111",
|
|
52
|
+
runKey: "t+1h",
|
|
53
|
+
issues: { title: "POST /checkout 500 rate elevated" },
|
|
54
|
+
evidenceSummary: "5xx rate rose after the deploy.",
|
|
55
|
+
planRevision: "changeMonitors/cm-1/planRevisions/3",
|
|
56
|
+
createTime: "2026-09-08T21:00:00Z",
|
|
57
|
+
description: "Checkout 500s are elevated.",
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const FACTORY_ISSUE_RESOURCE: FactoryIssueResourceFixture = {
|
|
61
|
+
name: FACTORY_ISSUE_NAME,
|
|
62
|
+
title: "Checkout 500s",
|
|
63
|
+
body: "5xx rate rose after the deploy.",
|
|
64
|
+
state: "STATE_OPEN",
|
|
65
|
+
createTime: "2026-09-08T21:00:00Z",
|
|
66
|
+
updateTime: "2026-09-08T21:00:00Z",
|
|
67
|
+
path: "checkout/500s",
|
|
68
|
+
etag: 'W/"1"',
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const CHECKPOINT_CREATED_PAYLOAD: CheckpointCreatedPayloadFixture = {
|
|
72
|
+
eventId: "evt-cp-1",
|
|
73
|
+
eventType: "checkpoint.created",
|
|
74
|
+
teamId: "team-1",
|
|
75
|
+
occurredAtMs: 1,
|
|
76
|
+
checkpoint: FACTORY_CHECKPOINT_RESOURCE,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const ISSUE_CREATED_PAYLOAD: IssueCreatedPayloadFixture = {
|
|
80
|
+
eventId: "evt-iss-1",
|
|
81
|
+
eventType: "issue.created",
|
|
82
|
+
teamId: "team-1",
|
|
83
|
+
occurredAtMs: 1,
|
|
84
|
+
issue: FACTORY_ISSUE_RESOURCE,
|
|
85
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sync
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
2
|
+
* Sync workspace trees onto an Agent Store so cloud-runtime turns read
|
|
3
|
+
* them from the store mount. Authored `agent/sandbox/workspace/**` seeds
|
|
4
|
+
* land at store-root `workspace/<path>` (see `buildCloudWorkspaceSection`).
|
|
5
|
+
* Per-turn `workspaceFiles` land at `sessions/<sessionId>/workspace/<path>`
|
|
6
|
+
* (see `buildCloudSessionWorkspaceSection`). Personal-key local+cloud
|
|
7
|
+
* nests both under `agent-serve/<agent>/`.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { readFile } from "node:fs/promises";
|
|
@@ -13,6 +13,15 @@ import { MEMORY_DIR_NAME } from "../memory.js";
|
|
|
13
13
|
import type { SeedFile } from "../types.js";
|
|
14
14
|
import { mirrorToStore, storeRelPath } from "./store-mirror.js";
|
|
15
15
|
|
|
16
|
+
export type WorkspaceFileBody =
|
|
17
|
+
| string
|
|
18
|
+
| { encoding: "base64"; data: string; mimeType?: string };
|
|
19
|
+
|
|
20
|
+
/** Path or encoding that can never land. Distinct from a store outage. */
|
|
21
|
+
export class WorkspaceFileRefusal extends Error {
|
|
22
|
+
override readonly name = "WorkspaceFileRefusal";
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
/**
|
|
17
26
|
* Mirror the seed tree onto the store at its authored relative paths and
|
|
18
27
|
* delete keys no seed claims so redeploys drop removed files. Every seed
|
|
@@ -30,7 +39,7 @@ export async function syncWorkspaceToStore(args: {
|
|
|
30
39
|
for (const seed of args.seedFiles) {
|
|
31
40
|
desired.set(
|
|
32
41
|
agentStoreKeys.workspaceFile(
|
|
33
|
-
|
|
42
|
+
workspaceRelPath(seed.relativePath),
|
|
34
43
|
workspacePrefix
|
|
35
44
|
),
|
|
36
45
|
await readFile(seed.sourcePath)
|
|
@@ -39,17 +48,80 @@ export async function syncWorkspaceToStore(args: {
|
|
|
39
48
|
await mirrorToStore({ sink: args.sink, prefix: workspacePrefix, desired });
|
|
40
49
|
}
|
|
41
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Replace the session workspace prefix with this turn's `workspaceFiles`.
|
|
53
|
+
* Keys the map does not claim are deleted so a later send cannot leave a
|
|
54
|
+
* stale `pr.json`. Every path validates before the store is touched.
|
|
55
|
+
* Returns the relative paths that landed, in send order.
|
|
56
|
+
*/
|
|
57
|
+
export async function syncSessionWorkspaceFiles(args: {
|
|
58
|
+
sink: FileSink;
|
|
59
|
+
files: Record<string, WorkspaceFileBody>;
|
|
60
|
+
workspacePrefix: string;
|
|
61
|
+
}): Promise<string[]> {
|
|
62
|
+
const desired = new Map<string, Uint8Array>();
|
|
63
|
+
const relPaths: string[] = [];
|
|
64
|
+
for (const [relativePath, contents] of Object.entries(args.files)) {
|
|
65
|
+
const rel = workspaceRelPath(relativePath);
|
|
66
|
+
desired.set(
|
|
67
|
+
agentStoreKeys.workspaceFile(rel, args.workspacePrefix),
|
|
68
|
+
workspaceFileBytes(relativePath, contents)
|
|
69
|
+
);
|
|
70
|
+
relPaths.push(rel);
|
|
71
|
+
}
|
|
72
|
+
await mirrorToStore({
|
|
73
|
+
sink: args.sink,
|
|
74
|
+
prefix: args.workspacePrefix,
|
|
75
|
+
desired,
|
|
76
|
+
});
|
|
77
|
+
return relPaths;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Delete every key under the session workspace prefix. */
|
|
81
|
+
export async function wipeSessionWorkspace(args: {
|
|
82
|
+
sink: FileSink;
|
|
83
|
+
workspacePrefix: string;
|
|
84
|
+
}): Promise<void> {
|
|
85
|
+
await mirrorToStore({
|
|
86
|
+
sink: args.sink,
|
|
87
|
+
prefix: args.workspacePrefix,
|
|
88
|
+
desired: new Map(),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
42
92
|
/**
|
|
43
93
|
* Same reservation as local materialization's `resolveWorkspaceWritePath`:
|
|
44
|
-
* `memory/` is the shared cross-session journal, so a seed under it
|
|
45
|
-
* the sync exactly as it fails a local first turn.
|
|
94
|
+
* `memory/` is the shared cross-session journal, so a seed or send under it
|
|
95
|
+
* fails the sync exactly as it fails a local first turn.
|
|
46
96
|
*/
|
|
47
|
-
function
|
|
48
|
-
|
|
97
|
+
function workspaceRelPath(relPath: string): string {
|
|
98
|
+
let rel: string;
|
|
99
|
+
try {
|
|
100
|
+
rel = storeRelPath(relPath, "workspace file");
|
|
101
|
+
} catch (error) {
|
|
102
|
+
throw new WorkspaceFileRefusal(
|
|
103
|
+
error instanceof Error ? error.message : String(error)
|
|
104
|
+
);
|
|
105
|
+
}
|
|
49
106
|
if (rel.split("/", 1)[0] === MEMORY_DIR_NAME) {
|
|
50
|
-
throw new
|
|
107
|
+
throw new WorkspaceFileRefusal(
|
|
51
108
|
`"${MEMORY_DIR_NAME}" is reserved for shared session memory; refusing to sync ${relPath}`
|
|
52
109
|
);
|
|
53
110
|
}
|
|
54
111
|
return rel;
|
|
55
112
|
}
|
|
113
|
+
|
|
114
|
+
function workspaceFileBytes(
|
|
115
|
+
relativePath: string,
|
|
116
|
+
contents: WorkspaceFileBody
|
|
117
|
+
): Uint8Array {
|
|
118
|
+
if (typeof contents === "string") {
|
|
119
|
+
return new TextEncoder().encode(contents);
|
|
120
|
+
}
|
|
121
|
+
if (contents.encoding === "base64") {
|
|
122
|
+
return new Uint8Array(Buffer.from(contents.data, "base64"));
|
|
123
|
+
}
|
|
124
|
+
throw new WorkspaceFileRefusal(
|
|
125
|
+
`Unsupported workspace file encoding for ${relativePath}`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
@@ -80,6 +80,26 @@ export function buildCloudWorkspaceSection(dir: string): string {
|
|
|
80
80
|
].join("\n");
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Per-turn preamble for cloud `workspaceFiles` after they land on the
|
|
85
|
+
* session store prefix (see `syncSessionWorkspaceFiles`). Omitted when
|
|
86
|
+
* the sync did not land.
|
|
87
|
+
*
|
|
88
|
+
* Same shared Agent Store mount as authored seeds — the session path is
|
|
89
|
+
* replace-per-send / task-end wipe lifetime, not a separate mount ACL.
|
|
90
|
+
*/
|
|
91
|
+
export function buildCloudSessionWorkspaceSection(
|
|
92
|
+
dir: string,
|
|
93
|
+
relPaths: readonly string[]
|
|
94
|
+
): string {
|
|
95
|
+
const listed = relPaths.map((path) => `\`${path}\``).join(", ");
|
|
96
|
+
return [
|
|
97
|
+
"## Session workspace files",
|
|
98
|
+
"",
|
|
99
|
+
`This turn's workspace files live at \`${dir}\` on this machine (${listed}). Read them with your normal file tools. They sit on the same shared Agent Store mount as authored workspace seeds; the session directory is replaced on the next send for this session, and task sessions remove it when they finish.`,
|
|
100
|
+
].join("\n");
|
|
101
|
+
}
|
|
102
|
+
|
|
83
103
|
/** Relative path of an agent-side tool script inside the session workspace. */
|
|
84
104
|
export function agentToolScriptPath(toolName: string): string {
|
|
85
105
|
return `.agent-serve/tools/${toolName}.sh`;
|
package/src/types.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { InteractionUpdate, SDKCustomTool, ToolName } from "@cursor/sdk";
|
|
12
12
|
import type { z } from "zod";
|
|
13
13
|
import type { ABConfigFile } from "./ab.js";
|
|
14
|
+
import type { FileSystem } from "./filesystem.js";
|
|
14
15
|
import type {
|
|
15
16
|
ContinuationClaim,
|
|
16
17
|
ContinuationIdentity,
|
|
@@ -169,6 +170,18 @@ export function toPublicCloudInfo(
|
|
|
169
170
|
};
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Session-scoped facts a `root` factory needs and does not otherwise
|
|
175
|
+
* have at `defineAgent` time. The factory returns a handle: each
|
|
176
|
+
* method must observe the current binding. Do not snapshot the tree.
|
|
177
|
+
*/
|
|
178
|
+
export interface RootContext {
|
|
179
|
+
sessionId: string;
|
|
180
|
+
agentName?: string;
|
|
181
|
+
continuationKey?: string;
|
|
182
|
+
host?: { files: HostFilesApi; reminders?: ReminderHostApi };
|
|
183
|
+
}
|
|
184
|
+
|
|
172
185
|
/** Input to `defineAgent` (authored at `agent/agent.ts`). */
|
|
173
186
|
export interface AgentConfig {
|
|
174
187
|
/**
|
|
@@ -190,10 +203,21 @@ export interface AgentConfig {
|
|
|
190
203
|
*/
|
|
191
204
|
instructions?: string;
|
|
192
205
|
/**
|
|
193
|
-
* Execution runtime. Defaults to `"local"`.
|
|
194
|
-
*
|
|
206
|
+
* Execution runtime. Defaults to `"local"`. Compatibility strings
|
|
207
|
+
* `"cloud"` and `"grokbot"` remain for agents that already ship; they
|
|
208
|
+
* are not a product surface. New agents omit this field.
|
|
195
209
|
*/
|
|
196
210
|
runtime?: AgentRuntime;
|
|
211
|
+
/**
|
|
212
|
+
* The FileSystem the model can see. Omit it and the root is the host
|
|
213
|
+
* disk. A static handle (`tempFs`, `unionFs`, ...) is that object on
|
|
214
|
+
* every session — writes are shared. Pass `(ctx) => …` and return a
|
|
215
|
+
* new handle per session when you want isolation. A factory that
|
|
216
|
+
* returns the same object still shares. Incompatible with
|
|
217
|
+
* {@link local} `cwd` / `workspaceDir` / `sandbox` and with
|
|
218
|
+
* {@link runtime} `"cloud"`.
|
|
219
|
+
*/
|
|
220
|
+
root?: FileSystem | ((ctx: RootContext) => FileSystem | Promise<FileSystem>);
|
|
197
221
|
/**
|
|
198
222
|
* Cloud agent defaults. Used when {@link runtime} is `"cloud"`, and as
|
|
199
223
|
* the base merged under per-session {@link SendMessageOptions.cloud}
|
|
@@ -262,7 +286,8 @@ export interface AgentConfig {
|
|
|
262
286
|
* deploys onto the v2 control plane (v2 APIs and schemas). Omitted
|
|
263
287
|
* channel `continuation` then inherits from declared events (`github.pr/v2`,
|
|
264
288
|
* `github.issue/v2`, `github.none/v2`, `slack.thread/v2`, `origin.pr/v2`,
|
|
265
|
-
* `deployments.deployment/v2`, `
|
|
289
|
+
* `deployments.deployment/v2`, `change_monitors.checkpoint/v2`,
|
|
290
|
+
* `issues.issue/v2`, `none/v2`). An explicit per-channel selector
|
|
266
291
|
* still overrides.
|
|
267
292
|
*
|
|
268
293
|
* ```ts
|
|
@@ -1901,8 +1926,9 @@ export interface SessionRecord {
|
|
|
1901
1926
|
*/
|
|
1902
1927
|
workspaceOverride?: string;
|
|
1903
1928
|
/**
|
|
1904
|
-
* One-shot files
|
|
1905
|
-
*
|
|
1929
|
+
* One-shot files for the next turn (see {@link SendMessageOptions.workspaceFiles}).
|
|
1930
|
+
* Local turns write them into the harness cwd. Cloud turns sync them onto
|
|
1931
|
+
* the session Agent Store prefix. Cleared after apply.
|
|
1906
1932
|
*/
|
|
1907
1933
|
pendingWorkspaceFiles?: Record<
|
|
1908
1934
|
string,
|
|
@@ -2087,12 +2113,12 @@ export interface SendMessageOptions {
|
|
|
2087
2113
|
*/
|
|
2088
2114
|
workspaceDir?: string;
|
|
2089
2115
|
/**
|
|
2090
|
-
* Relative path → contents
|
|
2091
|
-
*
|
|
2092
|
-
* the
|
|
2093
|
-
*
|
|
2094
|
-
*
|
|
2095
|
-
*
|
|
2116
|
+
* Relative path → contents for the next turn. Local turns write them into
|
|
2117
|
+
* the harness cwd after scaffold materialize. Cloud turns sync them onto
|
|
2118
|
+
* the session Agent Store prefix instead of the VM working directory. On
|
|
2119
|
+
* create, queued for the first turn; on resume, merged into any pending
|
|
2120
|
+
* files. Prefer this over {@link workspaceDir} when you only need to
|
|
2121
|
+
* inject a few host-prepared files. Values may be utf8 strings or
|
|
2096
2122
|
* `{ encoding: "base64", data }` blobs (Slack attachments, binary docs).
|
|
2097
2123
|
*/
|
|
2098
2124
|
workspaceFiles?: Record<
|
|
@@ -2520,6 +2546,13 @@ export interface ChannelMeta {
|
|
|
2520
2546
|
* to dispatch on. Extracted into the deploy manifest as `eventTypes`.
|
|
2521
2547
|
*/
|
|
2522
2548
|
deploymentEventTypes?: readonly string[];
|
|
2549
|
+
/**
|
|
2550
|
+
* For Change Monitor checkpoint and Factory issue packs: the factory
|
|
2551
|
+
* event types this channel is wired to dispatch on. Extracted into the
|
|
2552
|
+
* deploy manifest as `eventTypes`. Kept separate from
|
|
2553
|
+
* `deploymentEventTypes`.
|
|
2554
|
+
*/
|
|
2555
|
+
factoryEventTypes?: readonly string[];
|
|
2523
2556
|
/**
|
|
2524
2557
|
* For Slack packs with the opt-in channel watch: the allowlisted channels
|
|
2525
2558
|
* (ids or `#names`) this channel dispatches on without a mention. Surfaced
|
|
@@ -3122,6 +3155,11 @@ export interface ResolvedAgent {
|
|
|
3122
3155
|
instructions?: string;
|
|
3123
3156
|
/** Execution runtime. Root agents default to `"local"`. */
|
|
3124
3157
|
runtime: AgentRuntime;
|
|
3158
|
+
/**
|
|
3159
|
+
* Authored {@link AgentConfig.root}. The factory is persisted, not a
|
|
3160
|
+
* serialized tree. A resumed session calls it again (or reuses the handle).
|
|
3161
|
+
*/
|
|
3162
|
+
root?: FileSystem | ((ctx: RootContext) => FileSystem | Promise<FileSystem>);
|
|
3125
3163
|
/** Cloud options when {@link runtime} is `"cloud"`. */
|
|
3126
3164
|
cloud?: AgentCloudOptions;
|
|
3127
3165
|
/**
|
|
@@ -3274,6 +3312,8 @@ export interface AgentProjectInfo {
|
|
|
3274
3312
|
bitbucketWebhookEvents?: readonly string[];
|
|
3275
3313
|
/** Factory deployment event types the channel dispatches on, when declared. */
|
|
3276
3314
|
deploymentEventTypes?: readonly string[];
|
|
3315
|
+
/** Change Monitor checkpoint or Factory issue event types the channel dispatches on, when declared. */
|
|
3316
|
+
factoryEventTypes?: readonly string[];
|
|
3277
3317
|
/** Slack channels watched for posts (opt-in channel watch), when declared. */
|
|
3278
3318
|
slackChannelPosts?: readonly string[];
|
|
3279
3319
|
}>;
|
|
@@ -3324,10 +3364,17 @@ export interface RunnerTurnRequest {
|
|
|
3324
3364
|
sdkAgentId?: string;
|
|
3325
3365
|
/** Absolute path of the session's materialized workspace. */
|
|
3326
3366
|
workspaceDir: string;
|
|
3367
|
+
/** Resolved FileSystem handle when {@link AgentConfig.root} is set. */
|
|
3368
|
+
root?: FileSystem;
|
|
3327
3369
|
/** Run the local harness sandboxed ({@link AgentLocalOptions.sandbox}). */
|
|
3328
3370
|
sandbox?: boolean;
|
|
3329
3371
|
/** Built-in tool allowlist ({@link AgentConfig.tools}, resolved). */
|
|
3330
3372
|
tools?: ToolName[];
|
|
3373
|
+
/**
|
|
3374
|
+
* Native tools hidden on the Cursor SDK agent because synthesized
|
|
3375
|
+
* FileSystem tools own those names. Host-default omitted `tools` only.
|
|
3376
|
+
*/
|
|
3377
|
+
disallowedTools?: ToolName[];
|
|
3331
3378
|
/** Absolute path for runner-owned durable state (conversation store). */
|
|
3332
3379
|
runnerStateDir: string;
|
|
3333
3380
|
prompt: string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Grok Bot agents
|
|
2
|
+
|
|
3
|
+
Consults the Grok Bot agents you name. This agent stays in its own
|
|
4
|
+
conversation and reports the reply.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npx @cursor/july init ./grokbot --template grokbot-agents
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
`init` asks for the names shown in the Grok Bot app. Skip the prompt
|
|
11
|
+
with `--var agents="Plan Keeper, Chief of Staff"`.
|
|
12
|
+
|
|
13
|
+
## Run
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
agent-sdk login
|
|
17
|
+
agent-sdk dev
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
In the playground, ask it to talk to one of the names you entered. A
|
|
21
|
+
name outside the list is refused.
|
|
22
|
+
|
|
23
|
+
## Edit
|
|
24
|
+
|
|
25
|
+
- `agent/extensions/grokbot.ts`: who it may talk to
|
|
26
|
+
- `agent/instructions.md`: when to consult them
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Grok Bot agents
|
|
2
|
+
|
|
3
|
+
Consult the Grok Bot agents named in `agent/extensions/grokbot.ts`. Stay in this conversation and report the reply.
|
|
4
|
+
|
|
5
|
+
When someone asks who you can talk to, call `grokbot__list`. Do not send a message.
|
|
6
|
+
|
|
7
|
+
When the question belongs to one of those agents, use the consult skill. A name outside the list is refused.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineEval } from "@cursor/july/evals";
|
|
2
|
+
|
|
3
|
+
export default defineEval({
|
|
4
|
+
tags: ["smoke"],
|
|
5
|
+
cases: [
|
|
6
|
+
{
|
|
7
|
+
id: "list",
|
|
8
|
+
description: "Asked who it can talk to, it lists and does not send.",
|
|
9
|
+
async test(t) {
|
|
10
|
+
await t.send("Who can you talk to? List them. Do not message anyone.");
|
|
11
|
+
t.succeeded();
|
|
12
|
+
t.calledTool("grokbot__list");
|
|
13
|
+
t.notCalledTool("grokbot__ask");
|
|
14
|
+
t.notCalledTool("grokbot__interrupt");
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"questions": [
|
|
3
|
+
{
|
|
4
|
+
"id": "agents",
|
|
5
|
+
"prompt": "Which Grok Bot agents may this agent talk to?",
|
|
6
|
+
"hint": "Comma-separated names, as shown in the Grok Bot app.",
|
|
7
|
+
"placeholder": "Plan Keeper, Chief of Staff"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"replace": [
|
|
11
|
+
{
|
|
12
|
+
"file": "agent/extensions/grokbot.ts",
|
|
13
|
+
"find": "[\"Plan Keeper\"]",
|
|
14
|
+
"answer": "agents",
|
|
15
|
+
"as": "json-array"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "grokbot-agents",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Consults the Grok Bot agents you name.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"check": "tsc --noEmit",
|
|
8
|
+
"dev": "agent-sdk dev"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@cursor/july": "latest"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/node": "^22.14.0",
|
|
15
|
+
"typescript": "^5.8.0"
|
|
16
|
+
}
|
|
17
|
+
}
|