@crowdedkingdoms/crowdyjs 11.1.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +107 -0
- package/README.md +203 -0
- package/dist/crowdy-agent/browser-dispatcher.d.ts +41 -0
- package/dist/crowdy-agent/browser-dispatcher.d.ts.map +1 -0
- package/dist/crowdy-agent/browser-dispatcher.js +264 -0
- package/dist/crowdy-agent/controller.d.ts +144 -0
- package/dist/crowdy-agent/controller.d.ts.map +1 -0
- package/dist/crowdy-agent/controller.js +1239 -0
- package/dist/crowdy-agent/errors.d.ts +37 -0
- package/dist/crowdy-agent/errors.d.ts.map +1 -0
- package/dist/crowdy-agent/errors.js +107 -0
- package/dist/crowdy-agent/graphql-transport.d.ts +154 -0
- package/dist/crowdy-agent/graphql-transport.d.ts.map +1 -0
- package/dist/crowdy-agent/graphql-transport.js +854 -0
- package/dist/crowdy-agent/index.d.ts +16 -0
- package/dist/crowdy-agent/index.d.ts.map +1 -0
- package/dist/crowdy-agent/index.js +15 -0
- package/dist/crowdy-agent/registry.d.ts +29 -0
- package/dist/crowdy-agent/registry.d.ts.map +1 -0
- package/dist/crowdy-agent/registry.js +281 -0
- package/dist/crowdy-agent/schema.d.ts +72 -0
- package/dist/crowdy-agent/schema.d.ts.map +1 -0
- package/dist/crowdy-agent/schema.js +467 -0
- package/dist/crowdy-agent/studio-tools.d.ts +15 -0
- package/dist/crowdy-agent/studio-tools.d.ts.map +1 -0
- package/dist/crowdy-agent/studio-tools.js +280 -0
- package/dist/crowdy-agent/tool-descriptors.d.ts +4 -0
- package/dist/crowdy-agent/tool-descriptors.d.ts.map +1 -0
- package/dist/crowdy-agent/tool-descriptors.js +1049 -0
- package/dist/crowdy-agent/transport.d.ts +152 -0
- package/dist/crowdy-agent/transport.d.ts.map +1 -0
- package/dist/crowdy-agent/transport.js +27 -0
- package/dist/crowdy-agent/types.d.ts +328 -0
- package/dist/crowdy-agent/types.d.ts.map +1 -0
- package/dist/crowdy-agent/types.js +37 -0
- package/dist/crowdy-client.d.ts +3 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +6 -0
- package/dist/crowdy-studio/agent-dom-shell.d.ts +40 -0
- package/dist/crowdy-studio/agent-dom-shell.d.ts.map +1 -0
- package/dist/crowdy-studio/agent-dom-shell.js +354 -0
- package/dist/crowdy-studio/controller.d.ts +74 -4
- package/dist/crowdy-studio/controller.d.ts.map +1 -1
- package/dist/crowdy-studio/controller.js +450 -17
- package/dist/crowdy-studio/dom-shell.d.ts +4 -1
- package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
- package/dist/crowdy-studio/dom-shell.js +6 -1
- package/dist/crowdy-studio/index.d.ts +6 -3
- package/dist/crowdy-studio/index.d.ts.map +1 -1
- package/dist/crowdy-studio/index.js +3 -0
- package/dist/crowdy-studio/models.d.ts +67 -0
- package/dist/crowdy-studio/models.d.ts.map +1 -1
- package/dist/crowdy-studio/mount.d.ts +15 -0
- package/dist/crowdy-studio/mount.d.ts.map +1 -1
- package/dist/crowdy-studio/mount.js +129 -2
- package/dist/crowdy-studio/styles.d.ts +1 -1
- package/dist/crowdy-studio/styles.d.ts.map +1 -1
- package/dist/crowdy-studio/styles.js +2 -0
- package/dist/generated/graphql.d.ts +3753 -1
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +296 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/player-host/index.d.ts +5 -0
- package/dist/player-host/index.d.ts.map +1 -0
- package/dist/player-host/index.js +3 -0
- package/dist/player-host/lease-manager.d.ts +66 -0
- package/dist/player-host/lease-manager.d.ts.map +1 -0
- package/dist/player-host/lease-manager.js +428 -0
- package/dist/player-host/schemas.d.ts +9 -0
- package/dist/player-host/schemas.d.ts.map +1 -0
- package/dist/player-host/schemas.js +347 -0
- package/dist/player-host/tools.d.ts +13 -0
- package/dist/player-host/tools.d.ts.map +1 -0
- package/dist/player-host/tools.js +79 -0
- package/dist/player-host/types.d.ts +203 -0
- package/dist/player-host/types.d.ts.map +1 -0
- package/dist/player-host/types.js +1 -0
- package/package.json +12 -2
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { projectTargets, } from '../crowdy-studio/models.js';
|
|
2
|
+
import { sha256Digest } from './schema.js';
|
|
3
|
+
import { CrowdyAgentError } from './errors.js';
|
|
4
|
+
/** Exact browser tools backed by the same headless kernel as the human UI. */
|
|
5
|
+
export function createCrowdyStudioAgentTools(controller, options = {}) {
|
|
6
|
+
return Object.freeze({
|
|
7
|
+
'studio.context.get': () => {
|
|
8
|
+
const state = controller.getState();
|
|
9
|
+
const context = controller.getAgentContext();
|
|
10
|
+
return {
|
|
11
|
+
appRef: context.appRef,
|
|
12
|
+
...(context.projectRef ? { projectRef: context.projectRef } : {}),
|
|
13
|
+
gridRef: context.gridRef,
|
|
14
|
+
contextVersion: options.getContextVersion?.() ?? context.contextVersion,
|
|
15
|
+
saveState: state.saveState,
|
|
16
|
+
runtime: runtimeProjection(controller),
|
|
17
|
+
...(options.getClientEpoch?.()
|
|
18
|
+
? { clientEpoch: options.getClientEpoch() }
|
|
19
|
+
: {}),
|
|
20
|
+
leaseKinds: [...(options.getLeaseKinds?.() ?? [])],
|
|
21
|
+
...(options.getHostCapabilityRevision?.()
|
|
22
|
+
? {
|
|
23
|
+
hostCapabilityRevision: options.getHostCapabilityRevision(),
|
|
24
|
+
}
|
|
25
|
+
: {}),
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
'studio.state.get': () => {
|
|
29
|
+
const state = controller.getState();
|
|
30
|
+
return {
|
|
31
|
+
...(state.project
|
|
32
|
+
? { project: projectProjection(state.project) }
|
|
33
|
+
: {}),
|
|
34
|
+
openFiles: state.openFiles
|
|
35
|
+
.filter((file) => file.target)
|
|
36
|
+
.map((file) => ({
|
|
37
|
+
source: file.source,
|
|
38
|
+
target: file.target,
|
|
39
|
+
path: file.path,
|
|
40
|
+
})),
|
|
41
|
+
saveState: state.saveState,
|
|
42
|
+
runtime: runtimeProjection(controller),
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
'project.select': async (argumentsValue) => {
|
|
46
|
+
const projectRef = stringArgument(argumentsValue, 'projectRef');
|
|
47
|
+
await controller.switchProject(projectRef);
|
|
48
|
+
const project = requireProject(controller);
|
|
49
|
+
return {
|
|
50
|
+
selectedProjectRef: project.projectId,
|
|
51
|
+
revision: project.revision.id,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
'workspace.tab.open': (argumentsValue) => {
|
|
55
|
+
controller.openFile(fileRef(argumentsValue));
|
|
56
|
+
return { ok: true };
|
|
57
|
+
},
|
|
58
|
+
'workspace.tab.close': (argumentsValue) => {
|
|
59
|
+
controller.closeFile(fileRef(argumentsValue));
|
|
60
|
+
return { ok: true };
|
|
61
|
+
},
|
|
62
|
+
'diagnostics.local.get': () => ({
|
|
63
|
+
diagnostics: controller.getState().localDiagnostics.map((diagnostic) => ({
|
|
64
|
+
source: 'LOCAL_ADVISORY',
|
|
65
|
+
target: diagnostic.target,
|
|
66
|
+
path: diagnostic.path,
|
|
67
|
+
line: diagnostic.line,
|
|
68
|
+
column: diagnostic.column,
|
|
69
|
+
severity: diagnostic.severity.toUpperCase(),
|
|
70
|
+
...(diagnostic.code ? { code: diagnostic.code } : {}),
|
|
71
|
+
message: diagnostic.message,
|
|
72
|
+
})),
|
|
73
|
+
}),
|
|
74
|
+
'runtime.status.get': () => runtimeProjection(controller),
|
|
75
|
+
'runtime.test_draft': async (argumentsValue, context) => {
|
|
76
|
+
assertInvocationLease(context.invocation.leaseId, 'WORKSPACE', options);
|
|
77
|
+
const expectedRevision = stringArgument(argumentsValue, 'expectedRevision');
|
|
78
|
+
const targets = targetArguments(argumentsValue);
|
|
79
|
+
const result = await runStudioOperation(controller, context.signal, (operation) => controller.testDraftPlan({
|
|
80
|
+
expectedRevisionId: expectedRevision,
|
|
81
|
+
targets,
|
|
82
|
+
}, operation));
|
|
83
|
+
if (result.status !== 'RUNNING') {
|
|
84
|
+
throw new CrowdyAgentError('AGENT_TOOL_FAILED', result.message);
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
runtime: runtimeProjection(controller),
|
|
88
|
+
compiledTargets: [...result.targets],
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
'runtime.deploy_live': async (argumentsValue, context) => {
|
|
92
|
+
assertInvocationLease(context.invocation.leaseId, 'WORKSPACE', options);
|
|
93
|
+
if (!context.invocation.approvalGrant) {
|
|
94
|
+
throw new CrowdyAgentError('AGENT_APPROVAL_REQUIRED', 'Live deployment requires exact human approval');
|
|
95
|
+
}
|
|
96
|
+
const expectedHash = stringArgument(argumentsValue, 'projectContentHash');
|
|
97
|
+
const expectedRevision = stringArgument(argumentsValue, 'expectedRevision');
|
|
98
|
+
const targets = targetArguments(argumentsValue);
|
|
99
|
+
const pairingPreference = stringArgument(argumentsValue, 'pairingPreference');
|
|
100
|
+
const result = await runStudioOperation(controller, context.signal, (operation) => controller.deployLivePlan({
|
|
101
|
+
expectedRevisionId: expectedRevision,
|
|
102
|
+
targets,
|
|
103
|
+
pairingPreference,
|
|
104
|
+
projectContentHash: expectedHash,
|
|
105
|
+
}, operation));
|
|
106
|
+
if (result.status !== 'RUNNING') {
|
|
107
|
+
throw new CrowdyAgentError('AGENT_TOOL_FAILED', result.message);
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
runtime: runtimeProjection(controller),
|
|
111
|
+
deployedTargets: [...result.targets],
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
'runtime.invoke': async (argumentsValue, context) => {
|
|
115
|
+
const environment = stringArgument(argumentsValue, 'environment');
|
|
116
|
+
assertRuntimeEnvironment(controller, environment);
|
|
117
|
+
assertInvocationLease(context.invocation.leaseId, environment === 'LIVE' ? 'PLAY' : 'WORKSPACE', options);
|
|
118
|
+
if (environment === 'LIVE' && !context.invocation.approvalGrant) {
|
|
119
|
+
throw new CrowdyAgentError('AGENT_APPROVAL_REQUIRED', 'Live runtime invocation requires exact human approval');
|
|
120
|
+
}
|
|
121
|
+
const params = arrayArgument(argumentsValue, 'params').map((entry) => {
|
|
122
|
+
if (!isRecord(entry)) {
|
|
123
|
+
throw new CrowdyAgentError('AGENT_TOOL_INPUT_INVALID', 'Runtime parameter must be an object');
|
|
124
|
+
}
|
|
125
|
+
const name = stringArgument(entry, 'name');
|
|
126
|
+
const type = stringArgument(entry, 'type');
|
|
127
|
+
const value = stringArgument(entry, 'value');
|
|
128
|
+
if (type === 'BOOLEAN' && value !== 'true' && value !== 'false') {
|
|
129
|
+
throw new CrowdyAgentError('AGENT_TOOL_INPUT_INVALID', `Boolean parameter ${name} must be true or false`);
|
|
130
|
+
}
|
|
131
|
+
return [
|
|
132
|
+
name,
|
|
133
|
+
type === 'BOOLEAN' ? value === 'true' : value,
|
|
134
|
+
];
|
|
135
|
+
});
|
|
136
|
+
const result = await runStudioOperation(controller, context.signal, (operation) => controller.invoke(stringArgument(argumentsValue, 'exportName'), JSON.stringify(Object.fromEntries(params)), operation));
|
|
137
|
+
const value = result.resultJson ?? result.resultBase64 ?? '';
|
|
138
|
+
return {
|
|
139
|
+
resultType: result.resultJson
|
|
140
|
+
? 'TEXT'
|
|
141
|
+
: result.resultBase64
|
|
142
|
+
? 'BASE64'
|
|
143
|
+
: 'EMPTY',
|
|
144
|
+
result: value,
|
|
145
|
+
fuelUsed: result.fuelUsed ?? '0',
|
|
146
|
+
durationUs: result.durationUs ?? 0,
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
'runtime.stop': async () => {
|
|
150
|
+
const result = await controller.stopProject();
|
|
151
|
+
return {
|
|
152
|
+
serverStopped: result.serverStopped !== false,
|
|
153
|
+
clientStopped: result.clientStopped !== false,
|
|
154
|
+
failures: result.failures,
|
|
155
|
+
};
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function runtimeProjection(controller) {
|
|
160
|
+
const state = controller.getState();
|
|
161
|
+
return {
|
|
162
|
+
phase: state.runtime.phase,
|
|
163
|
+
savedRevision: state.runtimeSync.savedRevisionId ?? state.project?.revision.id ?? '0',
|
|
164
|
+
...(state.runtimeSync.runningRevisionId
|
|
165
|
+
? { runningRevision: state.runtimeSync.runningRevisionId }
|
|
166
|
+
: {}),
|
|
167
|
+
sync: state.runtimeSync.state,
|
|
168
|
+
...(state.runtime.target ? { target: state.runtime.target } : {}),
|
|
169
|
+
...(state.runtimeSync.deployment
|
|
170
|
+
? { draft: state.runtimeSync.deployment === 'DRAFT' }
|
|
171
|
+
: {}),
|
|
172
|
+
...(state.runtime.message ? { message: state.runtime.message } : {}),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function projectProjection(project) {
|
|
176
|
+
return {
|
|
177
|
+
projectId: project.projectId,
|
|
178
|
+
name: project.metadata.name,
|
|
179
|
+
...(project.metadata.description
|
|
180
|
+
? { description: project.metadata.description }
|
|
181
|
+
: {}),
|
|
182
|
+
kind: project.kind,
|
|
183
|
+
revision: project.revision.id,
|
|
184
|
+
files: project.files.map((file) => ({
|
|
185
|
+
target: file.target,
|
|
186
|
+
path: file.path,
|
|
187
|
+
contentHash: sha256Digest(file.content),
|
|
188
|
+
byteLength: new TextEncoder().encode(file.content).byteLength,
|
|
189
|
+
})),
|
|
190
|
+
...(project.metadata.serverModuleName
|
|
191
|
+
? { serverModuleName: project.metadata.serverModuleName }
|
|
192
|
+
: {}),
|
|
193
|
+
...(project.metadata.clientModuleName
|
|
194
|
+
? { clientModuleName: project.metadata.clientModuleName }
|
|
195
|
+
: {}),
|
|
196
|
+
pairingPreference: project.metadata.pairingPreference,
|
|
197
|
+
updatedAt: project.updatedAt,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function fileRef(value) {
|
|
201
|
+
const source = stringArgument(value, 'source');
|
|
202
|
+
const target = stringArgument(value, 'target');
|
|
203
|
+
const path = stringArgument(value, 'path');
|
|
204
|
+
const referenceRef = typeof value.referenceRef === 'string' ? value.referenceRef : undefined;
|
|
205
|
+
return {
|
|
206
|
+
source,
|
|
207
|
+
target,
|
|
208
|
+
path,
|
|
209
|
+
...(referenceRef ? { referenceId: referenceRef } : {}),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function requireProject(controller) {
|
|
213
|
+
const project = controller.getState().project;
|
|
214
|
+
if (!project) {
|
|
215
|
+
throw new CrowdyAgentError('AGENT_CONTEXT_CHANGED', 'No Crowdy Studio project is selected');
|
|
216
|
+
}
|
|
217
|
+
return project;
|
|
218
|
+
}
|
|
219
|
+
function stringArgument(value, name) {
|
|
220
|
+
const entry = value[name];
|
|
221
|
+
if (typeof entry !== 'string') {
|
|
222
|
+
throw new CrowdyAgentError('AGENT_TOOL_INPUT_INVALID', `${name} must be a string`, { field: name });
|
|
223
|
+
}
|
|
224
|
+
return entry;
|
|
225
|
+
}
|
|
226
|
+
function arrayArgument(value, name) {
|
|
227
|
+
const entry = value[name];
|
|
228
|
+
if (!Array.isArray(entry)) {
|
|
229
|
+
throw new CrowdyAgentError('AGENT_TOOL_INPUT_INVALID', `${name} must be an array`, { field: name });
|
|
230
|
+
}
|
|
231
|
+
return entry;
|
|
232
|
+
}
|
|
233
|
+
function targetArguments(value) {
|
|
234
|
+
return arrayArgument(value, 'targets').map((target) => {
|
|
235
|
+
if (target !== 'SERVER' && target !== 'CLIENT') {
|
|
236
|
+
throw new CrowdyAgentError('AGENT_TOOL_INPUT_INVALID', 'Runtime target must be SERVER or CLIENT', { field: 'targets' });
|
|
237
|
+
}
|
|
238
|
+
return target;
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
function isRecord(value) {
|
|
242
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
243
|
+
}
|
|
244
|
+
function assertInvocationLease(leaseId, kind, options) {
|
|
245
|
+
if (!leaseId) {
|
|
246
|
+
throw new CrowdyAgentError('AGENT_LEASE_REQUIRED', `${kind} lease is required for this runtime operation`);
|
|
247
|
+
}
|
|
248
|
+
if (options.isLeaseActive && !options.isLeaseActive(leaseId, kind)) {
|
|
249
|
+
throw new CrowdyAgentError('AGENT_LEASE_REVOKED', `${kind} lease is no longer active`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function assertRuntimeEnvironment(controller, environment) {
|
|
253
|
+
const runtime = controller.getState().runtimeSync;
|
|
254
|
+
if ((environment !== 'DRAFT' && environment !== 'LIVE') ||
|
|
255
|
+
runtime.state !== 'RUNNING_SAVED' ||
|
|
256
|
+
runtime.deployment !== environment) {
|
|
257
|
+
throw new CrowdyAgentError('AGENT_CONTEXT_STALE', `No exact saved ${environment} runtime is currently running`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async function runStudioOperation(controller, signal, operation) {
|
|
261
|
+
const agentOperation = controller.beginAgentOperation();
|
|
262
|
+
const abort = () => controller.cancelAgentOperation('Agent operation preempted before completion');
|
|
263
|
+
if (signal.aborted) {
|
|
264
|
+
abort();
|
|
265
|
+
throw new CrowdyAgentError('AGENT_CANCELLED', 'Agent browser operation was cancelled');
|
|
266
|
+
}
|
|
267
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
268
|
+
try {
|
|
269
|
+
const result = await operation(agentOperation);
|
|
270
|
+
if (signal.aborted) {
|
|
271
|
+
throw new CrowdyAgentError('AGENT_CANCELLED', 'Agent browser operation was cancelled');
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
signal.removeEventListener('abort', abort);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/** Keep the canonical target helper reachable for BWF host integrations. */
|
|
280
|
+
export const crowdyStudioAgentProjectTargets = projectTargets;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CrowdyAgentToolDescriptorV1 } from './types.js';
|
|
2
|
+
/** Complete minimum Studio and generic game registry for contract version 1. */
|
|
3
|
+
export declare const CROWDY_AGENT_TOOL_DESCRIPTORS_V1: readonly CrowdyAgentToolDescriptorV1[];
|
|
4
|
+
//# sourceMappingURL=tool-descriptors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-descriptors.d.ts","sourceRoot":"","sources":["../../src/crowdy-agent/tool-descriptors.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAMV,2BAA2B,EAG5B,MAAM,YAAY,CAAC;AA8lCpB,gFAAgF;AAChF,eAAO,MAAM,gCAAgC,EAAE,SAAS,2BAA2B,EAKhF,CAAC"}
|