@leg3ndy/otto-bridge 0.9.1 → 1.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.
@@ -0,0 +1,516 @@
1
+ function asRecord(value) {
2
+ return value && typeof value === "object" ? value : {};
3
+ }
4
+ function asArray(value) {
5
+ return Array.isArray(value) ? value : [];
6
+ }
7
+ function asString(value) {
8
+ return typeof value === "string" ? value.trim() : "";
9
+ }
10
+ function normalizeStep(step) {
11
+ const payload = asRecord(step);
12
+ const stepId = asString(payload.step_id);
13
+ if (!stepId) {
14
+ return null;
15
+ }
16
+ return {
17
+ step_id: stepId,
18
+ kind: asString(payload.kind) || "tool_call",
19
+ status: asString(payload.status) || undefined,
20
+ worker_id: asString(payload.worker_id) || undefined,
21
+ artifact_ids: asArray(payload.artifact_ids)
22
+ .map((item) => asString(item))
23
+ .filter(Boolean),
24
+ };
25
+ }
26
+ function normalizeArtifact(artifact) {
27
+ const payload = asRecord(artifact);
28
+ const artifactId = asString(payload.artifact_id);
29
+ if (!artifactId) {
30
+ return null;
31
+ }
32
+ return {
33
+ artifact_id: artifactId,
34
+ kind: asString(payload.kind) || undefined,
35
+ producer_step_id: asString(payload.producer_step_id) || undefined,
36
+ };
37
+ }
38
+ function normalizeWorkspaceRoot(root) {
39
+ const payload = asRecord(root);
40
+ const rootPath = asString(payload.path);
41
+ if (!rootPath) {
42
+ return null;
43
+ }
44
+ return {
45
+ root_id: asString(payload.root_id) || undefined,
46
+ path: rootPath,
47
+ kind: asString(payload.kind) || undefined,
48
+ scope_reason: asString(payload.scope_reason) || undefined,
49
+ action_types: asArray(payload.action_types)
50
+ .map((item) => asString(item))
51
+ .filter(Boolean),
52
+ source: asString(payload.source) || undefined,
53
+ };
54
+ }
55
+ function normalizeWorkspaceTarget(target) {
56
+ const payload = asRecord(target);
57
+ const targetPath = asString(payload.path);
58
+ if (!targetPath) {
59
+ return null;
60
+ }
61
+ return {
62
+ target_id: asString(payload.target_id) || undefined,
63
+ path: targetPath,
64
+ kind: asString(payload.kind) || undefined,
65
+ access_mode: asString(payload.access_mode) || undefined,
66
+ action_type: asString(payload.action_type) || undefined,
67
+ source: asString(payload.source) || undefined,
68
+ step_id: asString(payload.step_id) || undefined,
69
+ filename: asString(payload.filename) || undefined,
70
+ };
71
+ }
72
+ function normalizeInstructionBundleDescriptor(value) {
73
+ const payload = asRecord(value);
74
+ const entrypoints = asArray(payload.entrypoints)
75
+ .map((item) => asString(item))
76
+ .filter(Boolean);
77
+ const precedence = asArray(payload.precedence)
78
+ .map((item) => asString(item))
79
+ .filter(Boolean);
80
+ const resolver = asString(payload.resolver) || undefined;
81
+ if (!resolver && entrypoints.length === 0 && precedence.length === 0) {
82
+ return undefined;
83
+ }
84
+ return {
85
+ resolver,
86
+ entrypoints,
87
+ precedence,
88
+ };
89
+ }
90
+ function normalizeRepoManifestDescriptor(value) {
91
+ const payload = asRecord(value);
92
+ const markerPaths = asArray(payload.marker_paths)
93
+ .map((item) => asString(item))
94
+ .filter(Boolean);
95
+ const manifestPaths = asArray(payload.manifest_paths)
96
+ .map((item) => asString(item))
97
+ .filter(Boolean);
98
+ const lockfilePaths = asArray(payload.lockfile_paths)
99
+ .map((item) => asString(item))
100
+ .filter(Boolean);
101
+ const includeInstructionSources = typeof payload.include_instruction_sources === "boolean"
102
+ ? payload.include_instruction_sources
103
+ : undefined;
104
+ const resolver = asString(payload.resolver) || undefined;
105
+ const vcsHint = asString(payload.vcs_hint) || undefined;
106
+ if (!resolver && markerPaths.length === 0 && manifestPaths.length === 0 && lockfilePaths.length === 0 && includeInstructionSources === undefined && !vcsHint) {
107
+ return undefined;
108
+ }
109
+ return {
110
+ resolver,
111
+ marker_paths: markerPaths,
112
+ manifest_paths: manifestPaths,
113
+ lockfile_paths: lockfilePaths,
114
+ include_instruction_sources: includeInstructionSources,
115
+ vcs_hint: vcsHint,
116
+ };
117
+ }
118
+ function normalizeWorkspaceIndexDescriptor(value) {
119
+ const payload = asRecord(value);
120
+ const ignoredDirectoryNames = asArray(payload.ignored_directory_names)
121
+ .map((item) => asString(item))
122
+ .filter(Boolean);
123
+ const keyFilePatterns = asArray(payload.key_file_patterns)
124
+ .map((item) => asString(item))
125
+ .filter(Boolean);
126
+ const resolver = asString(payload.resolver) || undefined;
127
+ const maxDepth = Number.isFinite(Number(payload.max_depth)) ? Number(payload.max_depth) : undefined;
128
+ const maxDirectories = Number.isFinite(Number(payload.max_directories)) ? Number(payload.max_directories) : undefined;
129
+ const maxFiles = Number.isFinite(Number(payload.max_files)) ? Number(payload.max_files) : undefined;
130
+ if (!resolver && ignoredDirectoryNames.length === 0 && keyFilePatterns.length === 0 && maxDepth === undefined && maxDirectories === undefined && maxFiles === undefined) {
131
+ return undefined;
132
+ }
133
+ return {
134
+ resolver,
135
+ max_depth: maxDepth,
136
+ max_directories: maxDirectories,
137
+ max_files: maxFiles,
138
+ ignored_directory_names: ignoredDirectoryNames,
139
+ key_file_patterns: keyFilePatterns,
140
+ };
141
+ }
142
+ function normalizeWorkspaceMemory(value) {
143
+ const payload = asRecord(value);
144
+ const memoryId = asString(payload.memory_id) || undefined;
145
+ const workspaceId = asString(payload.workspace_id) || undefined;
146
+ const source = asString(payload.source) || undefined;
147
+ const jobCount = Number.isFinite(Number(payload.job_count)) ? Number(payload.job_count) : undefined;
148
+ const recentJobIds = asArray(payload.recent_job_ids)
149
+ .map((item) => asString(item))
150
+ .filter(Boolean);
151
+ const recentActionTypes = asArray(payload.recent_action_types)
152
+ .map((item) => asString(item))
153
+ .filter(Boolean);
154
+ const recentTargetPaths = asArray(payload.recent_target_paths)
155
+ .map((item) => asString(item))
156
+ .filter(Boolean);
157
+ const recentArtifactKinds = asArray(payload.recent_artifact_kinds)
158
+ .map((item) => asString(item))
159
+ .filter(Boolean);
160
+ const latestJobId = asString(payload.latest_job_id) || undefined;
161
+ const latestJobStatus = asString(payload.latest_job_status) || undefined;
162
+ const latestJobAt = asString(payload.latest_job_at) || undefined;
163
+ const instructionDigest = asString(payload.instruction_digest) || undefined;
164
+ const repoRoot = asString(payload.repo_root) || undefined;
165
+ const scopedRootPath = asString(payload.scoped_root_path) || undefined;
166
+ const summary = asString(payload.summary) || undefined;
167
+ const statusCounts = Object.fromEntries(Object.entries(asRecord(payload.status_counts))
168
+ .map(([key, count]) => [asString(key), Number(count)])
169
+ .filter(([key, count]) => key && Number.isFinite(count)));
170
+ const retentionPayload = asRecord(payload.retention);
171
+ const retention = Object.keys(retentionPayload).length > 0
172
+ ? {
173
+ max_job_count: Number.isFinite(Number(retentionPayload.max_job_count)) ? Number(retentionPayload.max_job_count) : undefined,
174
+ max_age_days: Number.isFinite(Number(retentionPayload.max_age_days)) ? Number(retentionPayload.max_age_days) : undefined,
175
+ filtered_job_count: Number.isFinite(Number(retentionPayload.filtered_job_count)) ? Number(retentionPayload.filtered_job_count) : undefined,
176
+ window_started_at: asString(retentionPayload.window_started_at) || undefined,
177
+ last_cleared_at: asString(retentionPayload.last_cleared_at) || undefined,
178
+ last_cleared_reason: asString(retentionPayload.last_cleared_reason) || undefined,
179
+ }
180
+ : undefined;
181
+ const usagePolicyPayload = asRecord(payload.usage_policy);
182
+ const usagePolicy = Object.keys(usagePolicyPayload).length > 0
183
+ ? {
184
+ profile_id: asString(usagePolicyPayload.profile_id) || undefined,
185
+ summary_mode: asString(usagePolicyPayload.summary_mode) || undefined,
186
+ include_action_types: typeof usagePolicyPayload.include_action_types === "boolean" ? usagePolicyPayload.include_action_types : undefined,
187
+ include_target_paths: typeof usagePolicyPayload.include_target_paths === "boolean" ? usagePolicyPayload.include_target_paths : undefined,
188
+ include_artifact_kinds: typeof usagePolicyPayload.include_artifact_kinds === "boolean" ? usagePolicyPayload.include_artifact_kinds : undefined,
189
+ include_failed_jobs: typeof usagePolicyPayload.include_failed_jobs === "boolean" ? usagePolicyPayload.include_failed_jobs : undefined,
190
+ resettable: typeof usagePolicyPayload.resettable === "boolean" ? usagePolicyPayload.resettable : undefined,
191
+ }
192
+ : undefined;
193
+ if (!memoryId && !workspaceId && !source && jobCount === undefined && recentJobIds.length === 0 && recentActionTypes.length === 0 && recentTargetPaths.length === 0 && recentArtifactKinds.length === 0 && !latestJobId && !latestJobStatus && !latestJobAt && !instructionDigest && !repoRoot && !scopedRootPath && !summary && Object.keys(statusCounts).length === 0 && !retention && !usagePolicy) {
194
+ return undefined;
195
+ }
196
+ return {
197
+ memory_id: memoryId,
198
+ workspace_id: workspaceId,
199
+ source,
200
+ job_count: jobCount,
201
+ recent_job_ids: recentJobIds,
202
+ recent_action_types: recentActionTypes,
203
+ recent_target_paths: recentTargetPaths,
204
+ recent_artifact_kinds: recentArtifactKinds,
205
+ latest_job_id: latestJobId,
206
+ latest_job_status: latestJobStatus,
207
+ latest_job_at: latestJobAt,
208
+ instruction_digest: instructionDigest,
209
+ repo_root: repoRoot,
210
+ scoped_root_path: scopedRootPath,
211
+ summary,
212
+ status_counts: statusCounts,
213
+ retention,
214
+ usage_policy: usagePolicy,
215
+ };
216
+ }
217
+ function normalizeWorkspacePolicy(value) {
218
+ const payload = asRecord(value);
219
+ const profileId = asString(payload.profile_id) || undefined;
220
+ const title = asString(payload.title) || undefined;
221
+ const summary = asString(payload.summary) || undefined;
222
+ const rationale = asString(payload.rationale) || undefined;
223
+ const allowedActionTypes = asArray(payload.allowed_action_types)
224
+ .map((item) => asString(item).toLowerCase())
225
+ .filter(Boolean);
226
+ const blockedActionTypes = asArray(payload.blocked_action_types)
227
+ .map((item) => asString(item).toLowerCase())
228
+ .filter(Boolean);
229
+ const requiresConfirmationActionTypes = asArray(payload.requires_confirmation_action_types)
230
+ .map((item) => asString(item).toLowerCase())
231
+ .filter(Boolean);
232
+ const enforcedBy = asArray(payload.enforced_by)
233
+ .map((item) => asString(item))
234
+ .filter(Boolean);
235
+ const allowShell = typeof payload.allow_shell === "boolean" ? payload.allow_shell : undefined;
236
+ const allowCodeWrite = typeof payload.allow_code_write === "boolean" ? payload.allow_code_write : undefined;
237
+ const allowDestructive = typeof payload.allow_destructive === "boolean" ? payload.allow_destructive : undefined;
238
+ const allowRelease = typeof payload.allow_release === "boolean" ? payload.allow_release : undefined;
239
+ if (!profileId && !title && !summary && allowedActionTypes.length === 0 && blockedActionTypes.length === 0 && requiresConfirmationActionTypes.length === 0 && !rationale && allowShell === undefined && allowCodeWrite === undefined && allowDestructive === undefined && allowRelease === undefined && enforcedBy.length === 0) {
240
+ return undefined;
241
+ }
242
+ return {
243
+ profile_id: profileId,
244
+ title,
245
+ summary,
246
+ allowed_action_types: allowedActionTypes,
247
+ blocked_action_types: blockedActionTypes,
248
+ requires_confirmation_action_types: requiresConfirmationActionTypes,
249
+ rationale,
250
+ allow_shell: allowShell,
251
+ allow_code_write: allowCodeWrite,
252
+ allow_destructive: allowDestructive,
253
+ allow_release: allowRelease,
254
+ enforced_by: enforcedBy,
255
+ };
256
+ }
257
+ function normalizeWorkerProfile(value) {
258
+ const payload = asRecord(value);
259
+ const workerId = asString(payload.worker_id);
260
+ if (!workerId) {
261
+ return null;
262
+ }
263
+ return {
264
+ worker_id: workerId,
265
+ title: asString(payload.title) || undefined,
266
+ summary: asString(payload.summary) || undefined,
267
+ action_types: asArray(payload.action_types)
268
+ .map((item) => asString(item))
269
+ .filter(Boolean),
270
+ responsibilities: asArray(payload.responsibilities)
271
+ .map((item) => asString(item))
272
+ .filter(Boolean),
273
+ produces_artifact_kinds: asArray(payload.produces_artifact_kinds)
274
+ .map((item) => asString(item))
275
+ .filter(Boolean),
276
+ write_scope: asString(payload.write_scope) || undefined,
277
+ requires_confirmation: typeof payload.requires_confirmation === "boolean"
278
+ ? payload.requires_confirmation
279
+ : undefined,
280
+ };
281
+ }
282
+ function normalizeWorkerExecutionPolicy(value) {
283
+ const payload = asRecord(value);
284
+ const workerId = asString(payload.worker_id);
285
+ if (!workerId) {
286
+ return null;
287
+ }
288
+ const budgetSeconds = Number.isFinite(Number(payload.budget_seconds)) ? Number(payload.budget_seconds) : undefined;
289
+ const timeoutSeconds = Number.isFinite(Number(payload.timeout_seconds)) ? Number(payload.timeout_seconds) : undefined;
290
+ const retryLimit = Number.isFinite(Number(payload.retry_limit)) ? Number(payload.retry_limit) : undefined;
291
+ const maxParallelTasks = Number.isFinite(Number(payload.max_parallel_tasks)) ? Number(payload.max_parallel_tasks) : undefined;
292
+ return {
293
+ worker_id: workerId,
294
+ budget_seconds: budgetSeconds,
295
+ timeout_seconds: timeoutSeconds,
296
+ retry_limit: retryLimit,
297
+ max_parallel_tasks: maxParallelTasks,
298
+ };
299
+ }
300
+ function normalizeCommandPack(value) {
301
+ const payload = asRecord(value);
302
+ const packId = asString(payload.pack_id);
303
+ if (!packId) {
304
+ return null;
305
+ }
306
+ return {
307
+ pack_id: packId,
308
+ title: asString(payload.title) || undefined,
309
+ summary: asString(payload.summary) || undefined,
310
+ selected: typeof payload.selected === "boolean" ? payload.selected : undefined,
311
+ intensity: asString(payload.intensity) || undefined,
312
+ reason: asString(payload.reason) || undefined,
313
+ worker_ids: asArray(payload.worker_ids)
314
+ .map((item) => asString(item))
315
+ .filter(Boolean),
316
+ prompt_hints: asArray(payload.prompt_hints)
317
+ .map((item) => asString(item))
318
+ .filter(Boolean),
319
+ };
320
+ }
321
+ function normalizeInstructionUpdate(value) {
322
+ const payload = asRecord(value);
323
+ const updaterId = asString(payload.updater_id);
324
+ if (!updaterId) {
325
+ return undefined;
326
+ }
327
+ return {
328
+ updater_id: updaterId,
329
+ resolver: asString(payload.resolver) || undefined,
330
+ selected: typeof payload.selected === "boolean" ? payload.selected : undefined,
331
+ reason: asString(payload.reason) || undefined,
332
+ source_entrypoints: asArray(payload.source_entrypoints)
333
+ .map((item) => asString(item))
334
+ .filter(Boolean),
335
+ target_paths: asArray(payload.target_paths)
336
+ .map((item) => asString(item))
337
+ .filter(Boolean),
338
+ recommended_validation_stage_ids: asArray(payload.recommended_validation_stage_ids)
339
+ .map((item) => asString(item))
340
+ .filter(Boolean),
341
+ };
342
+ }
343
+ function normalizeValidationLadderStage(value) {
344
+ const payload = asRecord(value);
345
+ const stageId = asString(payload.stage_id);
346
+ if (!stageId) {
347
+ return null;
348
+ }
349
+ const order = Number.isFinite(Number(payload.order)) ? Number(payload.order) : undefined;
350
+ return {
351
+ stage_id: stageId,
352
+ title: asString(payload.title) || undefined,
353
+ order,
354
+ required: typeof payload.required === "boolean" ? payload.required : undefined,
355
+ profile: asString(payload.profile) || undefined,
356
+ command_hint: asString(payload.command_hint) || undefined,
357
+ stack_tags: asArray(payload.stack_tags)
358
+ .map((item) => asString(item).toLowerCase())
359
+ .filter(Boolean),
360
+ };
361
+ }
362
+ function normalizeValidationLadder(value) {
363
+ const payload = asRecord(value);
364
+ const ladderId = asString(payload.ladder_id);
365
+ if (!ladderId) {
366
+ return undefined;
367
+ }
368
+ return {
369
+ ladder_id: ladderId,
370
+ resolver: asString(payload.resolver) || undefined,
371
+ title: asString(payload.title) || undefined,
372
+ summary: asString(payload.summary) || undefined,
373
+ stop_on_failure: typeof payload.stop_on_failure === "boolean" ? payload.stop_on_failure : undefined,
374
+ selected_command_pack_id: asString(payload.selected_command_pack_id) || undefined,
375
+ stages: asArray(payload.stages)
376
+ .map((item) => normalizeValidationLadderStage(item))
377
+ .filter((item) => Boolean(item)),
378
+ };
379
+ }
380
+ function normalizeHookBus(value) {
381
+ const payload = asRecord(value);
382
+ const busId = asString(payload.bus_id) || undefined;
383
+ const resolver = asString(payload.resolver) || undefined;
384
+ const summary = asString(payload.summary) || undefined;
385
+ const events = asArray(payload.events)
386
+ .map((item) => asString(item))
387
+ .filter(Boolean);
388
+ const sinks = asArray(payload.sinks)
389
+ .map((item) => asString(item))
390
+ .filter(Boolean);
391
+ if (!busId && !resolver && !summary && events.length === 0 && sinks.length === 0) {
392
+ return undefined;
393
+ }
394
+ return {
395
+ bus_id: busId,
396
+ resolver,
397
+ summary,
398
+ events,
399
+ sinks,
400
+ replay_enabled: typeof payload.replay_enabled === "boolean" ? payload.replay_enabled : undefined,
401
+ metrics_enabled: typeof payload.metrics_enabled === "boolean" ? payload.metrics_enabled : undefined,
402
+ enforcement_enabled: typeof payload.enforcement_enabled === "boolean" ? payload.enforcement_enabled : undefined,
403
+ };
404
+ }
405
+ function normalizeWorkspaceContext(value) {
406
+ const payload = asRecord(value);
407
+ const roots = asArray(payload.roots)
408
+ .map((item) => normalizeWorkspaceRoot(item))
409
+ .filter((item) => Boolean(item));
410
+ const targets = asArray(payload.targets)
411
+ .map((item) => normalizeWorkspaceTarget(item))
412
+ .filter((item) => Boolean(item));
413
+ const instructionBundle = normalizeInstructionBundleDescriptor(payload.instruction_bundle);
414
+ const repoManifest = normalizeRepoManifestDescriptor(payload.repo_manifest);
415
+ const workspaceIndex = normalizeWorkspaceIndexDescriptor(payload.workspace_index);
416
+ const workspaceMemory = normalizeWorkspaceMemory(payload.workspace_memory);
417
+ const workspacePolicy = normalizeWorkspacePolicy(payload.workspace_policy);
418
+ const workspaceId = asString(payload.workspace_id) || undefined;
419
+ if (!workspaceId && roots.length === 0 && targets.length === 0 && !instructionBundle && !repoManifest && !workspaceIndex && !workspaceMemory && !workspacePolicy) {
420
+ return undefined;
421
+ }
422
+ return {
423
+ workspace_id: workspaceId,
424
+ roots,
425
+ targets,
426
+ instruction_bundle: instructionBundle,
427
+ repo_manifest: repoManifest,
428
+ workspace_index: workspaceIndex,
429
+ workspace_memory: workspaceMemory,
430
+ workspace_policy: workspacePolicy,
431
+ };
432
+ }
433
+ export function parseJobRuntimeManifest(job) {
434
+ const payload = asRecord(job.payload);
435
+ const runtimeState = asRecord(payload.runtime_state);
436
+ const runtimeContract = asRecord(payload.runtime_contract);
437
+ const executionGraph = asRecord(runtimeContract.execution_graph);
438
+ const steps = asArray(executionGraph.steps)
439
+ .map((item) => normalizeStep(item))
440
+ .filter((item) => Boolean(item));
441
+ const expectedArtifacts = asArray(runtimeContract.expected_artifacts)
442
+ .map((item) => normalizeArtifact(item))
443
+ .filter((item) => Boolean(item));
444
+ const workerProfiles = asArray(runtimeContract.worker_profiles)
445
+ .map((item) => normalizeWorkerProfile(item))
446
+ .filter((item) => Boolean(item));
447
+ const workerExecution = asArray(runtimeContract.worker_execution)
448
+ .map((item) => normalizeWorkerExecutionPolicy(item))
449
+ .filter((item) => Boolean(item));
450
+ const commandPacks = asArray(runtimeContract.command_packs)
451
+ .map((item) => normalizeCommandPack(item))
452
+ .filter((item) => Boolean(item));
453
+ const approvalStepId = steps.find((step) => step.kind === "approval_gate")?.step_id;
454
+ const toolSteps = steps.filter((step) => step.kind === "tool_call");
455
+ const executionStepId = toolSteps[0]?.step_id;
456
+ const finalizeStepId = steps.find((step) => step.kind === "finalize")?.step_id;
457
+ return {
458
+ graphId: asString(runtimeState.graph_id) || asString(executionGraph.graph_id) || undefined,
459
+ currentStepId: asString(runtimeState.current_step_id) || undefined,
460
+ requiresConfirmation: payload.requires_confirmation === true,
461
+ steps,
462
+ toolSteps,
463
+ expectedArtifacts,
464
+ workerProfiles,
465
+ workerExecution,
466
+ commandPacks,
467
+ instructionUpdate: normalizeInstructionUpdate(runtimeContract.instruction_update),
468
+ validationLadder: normalizeValidationLadder(runtimeContract.validation_ladder),
469
+ hookBus: normalizeHookBus(runtimeContract.hook_bus),
470
+ approvalStepId,
471
+ executionStepId,
472
+ finalizeStepId,
473
+ workspaceContext: normalizeWorkspaceContext(runtimeContract.workspace_context),
474
+ };
475
+ }
476
+ export function runtimeStepIdForActionIndex(manifest, actionIndex) {
477
+ if (actionIndex < 0) {
478
+ return undefined;
479
+ }
480
+ return manifest.toolSteps[actionIndex]?.step_id;
481
+ }
482
+ export function runtimeStepIdForEvent(manifest, eventType) {
483
+ if (eventType === "confirm_required") {
484
+ return manifest.approvalStepId || manifest.currentStepId || manifest.executionStepId;
485
+ }
486
+ if (eventType === "accepted") {
487
+ if (manifest.requiresConfirmation && manifest.approvalStepId) {
488
+ return manifest.approvalStepId;
489
+ }
490
+ return manifest.executionStepId || manifest.currentStepId || manifest.finalizeStepId;
491
+ }
492
+ if (eventType === "progress") {
493
+ return manifest.executionStepId || manifest.currentStepId || manifest.finalizeStepId;
494
+ }
495
+ if (eventType === "completed") {
496
+ return manifest.finalizeStepId || manifest.currentStepId || manifest.executionStepId;
497
+ }
498
+ return manifest.currentStepId || manifest.executionStepId || manifest.finalizeStepId || manifest.approvalStepId;
499
+ }
500
+ export function runtimeExpectedArtifactIdForActionIndex(manifest, actionIndex, expectedKind) {
501
+ const stepId = runtimeStepIdForActionIndex(manifest, actionIndex);
502
+ if (!stepId) {
503
+ return undefined;
504
+ }
505
+ const normalizedExpectedKind = asString(expectedKind).toLowerCase();
506
+ const exact = manifest.expectedArtifacts.find((artifact) => {
507
+ if (asString(artifact.producer_step_id) !== stepId) {
508
+ return false;
509
+ }
510
+ if (!normalizedExpectedKind) {
511
+ return true;
512
+ }
513
+ return asString(artifact.kind).toLowerCase() === normalizedExpectedKind;
514
+ });
515
+ return exact?.artifact_id;
516
+ }
@@ -65,6 +65,170 @@ const NATIVE_MACOS_BASE_TOOLS = [
65
65
  mode: "observe",
66
66
  action_types: ["read_file"],
67
67
  },
68
+ {
69
+ id: "filesystem.write_text",
70
+ title: "Escrita de arquivo de texto",
71
+ description: "Cria ou atualiza arquivos .txt em caminhos locais, incluindo Desktop e outras pastas do usuario.",
72
+ category: "filesystem",
73
+ mode: "write",
74
+ action_types: ["write_text_file"],
75
+ },
76
+ {
77
+ id: "filesystem.write_json",
78
+ title: "Escrita de arquivo JSON",
79
+ description: "Grava arquivos JSON estruturados em caminhos locais do workspace.",
80
+ category: "filesystem",
81
+ mode: "write",
82
+ action_types: ["write_json_file"],
83
+ },
84
+ {
85
+ id: "workspace.patch",
86
+ title: "Aplicar patch no workspace",
87
+ description: "Aplica um patch estruturado em arquivos do workspace ativo e devolve um patch_set auditavel.",
88
+ category: "filesystem",
89
+ mode: "write",
90
+ action_types: ["apply_patch"],
91
+ },
92
+ {
93
+ id: "filesystem.mkdir",
94
+ title: "Criar pasta local",
95
+ description: "Cria pastas locais dentro do workspace ativo.",
96
+ category: "filesystem",
97
+ mode: "write",
98
+ action_types: ["mkdir"],
99
+ },
100
+ {
101
+ id: "filesystem.move",
102
+ title: "Mover item local",
103
+ description: "Move ou renomeia arquivos e pastas locais dentro do workspace ativo.",
104
+ category: "filesystem",
105
+ mode: "write",
106
+ action_types: ["move_file"],
107
+ requires_confirmation: true,
108
+ },
109
+ {
110
+ id: "filesystem.trash",
111
+ title: "Mover item para a Lixeira",
112
+ description: "Move arquivos e pastas locais para a Lixeira do macOS com confirmação.",
113
+ category: "filesystem",
114
+ mode: "write",
115
+ action_types: ["trash_path"],
116
+ requires_confirmation: true,
117
+ },
118
+ {
119
+ id: "filesystem.delete",
120
+ title: "Apagar arquivo local",
121
+ description: "Apaga permanentemente um arquivo local dentro do workspace ativo com confirmação.",
122
+ category: "filesystem",
123
+ mode: "write",
124
+ action_types: ["delete_file"],
125
+ requires_confirmation: true,
126
+ },
127
+ {
128
+ id: "git.status",
129
+ title: "Estado do Git",
130
+ description: "Lê branch, staged, unstaged e arquivos modificados do repositório local ativo.",
131
+ category: "git",
132
+ mode: "observe",
133
+ action_types: ["git_status"],
134
+ },
135
+ {
136
+ id: "git.diff",
137
+ title: "Diff do Git",
138
+ description: "Lê o diff atual ou staged do repositório local ativo.",
139
+ category: "git",
140
+ mode: "observe",
141
+ action_types: ["git_diff"],
142
+ },
143
+ {
144
+ id: "git.stage",
145
+ title: "Stage do Git",
146
+ description: "Prepara arquivos ou todas as mudanças pendentes no stage do repositório local ativo.",
147
+ category: "git",
148
+ mode: "write",
149
+ action_types: ["git_add"],
150
+ requires_confirmation: true,
151
+ },
152
+ {
153
+ id: "git.commit",
154
+ title: "Commit do Git",
155
+ description: "Cria um commit local no repositório ativo com mensagem explícita.",
156
+ category: "git",
157
+ mode: "write",
158
+ action_types: ["git_commit"],
159
+ requires_confirmation: true,
160
+ },
161
+ {
162
+ id: "git.push",
163
+ title: "Push do Git",
164
+ description: "Envia a branch local do repositório ativo para o remote configurado.",
165
+ category: "git",
166
+ mode: "write",
167
+ action_types: ["git_push"],
168
+ requires_confirmation: true,
169
+ },
170
+ {
171
+ id: "git.clone",
172
+ title: "Clone do Git",
173
+ description: "Clona um repositório Git em um destino local declarado dentro do workspace ativo.",
174
+ category: "git",
175
+ mode: "write",
176
+ action_types: ["git_clone"],
177
+ requires_confirmation: true,
178
+ },
179
+ {
180
+ id: "git.fetch",
181
+ title: "Fetch do Git",
182
+ description: "Atualiza refs e branches remotas do repositório local ativo.",
183
+ category: "git",
184
+ mode: "write",
185
+ action_types: ["git_fetch"],
186
+ requires_confirmation: true,
187
+ },
188
+ {
189
+ id: "git.checkout",
190
+ title: "Checkout do Git",
191
+ description: "Troca branch, cria branch local ou entra em detached HEAD no repositório ativo.",
192
+ category: "git",
193
+ mode: "write",
194
+ action_types: ["git_checkout"],
195
+ requires_confirmation: true,
196
+ },
197
+ {
198
+ id: "git.rebase",
199
+ title: "Rebase do Git",
200
+ description: "Rebaseia a branch atual sobre uma branch ou ref alvo do repositório ativo.",
201
+ category: "git",
202
+ mode: "write",
203
+ action_types: ["git_rebase"],
204
+ requires_confirmation: true,
205
+ },
206
+ {
207
+ id: "git.merge",
208
+ title: "Merge do Git",
209
+ description: "Mescla uma branch ou ref alvo na branch atual do repositório ativo.",
210
+ category: "git",
211
+ mode: "write",
212
+ action_types: ["git_merge"],
213
+ requires_confirmation: true,
214
+ },
215
+ {
216
+ id: "git.tag",
217
+ title: "Tag do Git",
218
+ description: "Cria uma tag local no repositório ativo com nome e anotação auditáveis.",
219
+ category: "git",
220
+ mode: "write",
221
+ action_types: ["git_tag"],
222
+ requires_confirmation: true,
223
+ },
224
+ {
225
+ id: "workspace.tests",
226
+ title: "Executar testes",
227
+ description: "Roda testes automatizados ou perfis de validacao do projeto dentro do workspace ativo e devolve relatório estruturado.",
228
+ category: "validation",
229
+ mode: "control",
230
+ action_types: ["run_tests"],
231
+ },
68
232
  {
69
233
  id: "system.health",
70
234
  title: "Status do Mac",