maka-agent 0.2.0-dev.6.20260830 → 0.2.0-dev.8.20260830

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.
Files changed (29) hide show
  1. package/native/runtime-host-peer/prebuilds/win32-x64/maka_runtime_host_peer.node +0 -0
  2. package/node_modules/@maka/core/dist/agent-run.js +0 -2
  3. package/node_modules/@maka/core/dist/foreign-session.js +1 -1
  4. package/node_modules/@maka/core/dist/task-ledger.js +6 -134
  5. package/node_modules/@maka/core/dist/usage-record-schema.js +1 -0
  6. package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +3 -115
  7. package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +4 -18
  8. package/node_modules/@maka/runtime/dist/context-budget.js +0 -1
  9. package/node_modules/@maka/runtime/dist/plan-mode.js +0 -65
  10. package/node_modules/@maka/runtime/dist/run-trace.js +0 -10
  11. package/node_modules/@maka/runtime/dist/runtime-kernel.js +0 -1
  12. package/node_modules/@maka/runtime/dist/sandbox/index.js +0 -1
  13. package/node_modules/@maka/runtime/dist/sandbox/linux-sandbox.js +0 -12
  14. package/node_modules/@maka/runtime/dist/sandbox/macos-seatbelt.js +0 -12
  15. package/node_modules/@maka/runtime/dist/sandbox/sandbox-manager.js +0 -35
  16. package/node_modules/@maka/runtime/dist/sandbox/windows-sandbox.js +0 -12
  17. package/node_modules/@maka/runtime/dist/shell-detect.js +3 -7
  18. package/node_modules/@maka/runtime/dist/shell-run-contract.js +0 -1
  19. package/node_modules/@maka/runtime/dist/shell-run-manager.js +1 -39
  20. package/node_modules/@maka/runtime/dist/shell-tools.js +1 -1
  21. package/node_modules/@maka/runtime/dist/task-ledger-tools.js +2 -2
  22. package/node_modules/@maka/runtime/package.json +0 -1
  23. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +1 -8
  24. package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +0 -6
  25. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +2 -58
  26. package/package.json +1 -1
  27. package/node_modules/@maka/runtime/dist/sandbox/diagnostics.js +0 -285
  28. package/node_modules/@maka/runtime/dist/system-prompt/sandbox-context-prompt.js +0 -77
  29. package/node_modules/@maka/runtime/dist/system-prompt/session-environment-prompt.js +0 -47
@@ -128,41 +128,6 @@ export class SandboxManager {
128
128
  return false;
129
129
  return backend.canEnforceProfile?.(input.profile) ?? true;
130
130
  }
131
- probe(request) {
132
- const selected = this.selectInitial({
133
- profile: request.command.profile,
134
- preference: request.preference,
135
- platform: request.platform,
136
- });
137
- if (!selected.ok)
138
- return selected;
139
- if (selected.sandboxType === 'none') {
140
- return {
141
- ok: true,
142
- executable: request.command.program,
143
- sandboxType: 'none',
144
- requiresSandbox: false,
145
- preference: selected.preference,
146
- };
147
- }
148
- const backend = this.backends.get(selected.sandboxType);
149
- if (!backend) {
150
- return {
151
- ok: false,
152
- reason: 'backend_not_available',
153
- sandboxType: selected.sandboxType,
154
- requiresSandbox: selected.requiresSandbox,
155
- platform: selected.platform,
156
- preference: selected.preference,
157
- message: `Sandbox backend ${selected.sandboxType} is not registered.`,
158
- };
159
- }
160
- return backend.probe({
161
- ...request,
162
- preference: selected.preference,
163
- platform: selected.platform,
164
- });
165
- }
166
131
  transform(request) {
167
132
  const selected = this.selectInitial({
168
133
  profile: request.command.profile,
@@ -70,18 +70,6 @@ export class WindowsBrokerSandboxBackend {
70
70
  profile.fileSystem.kind === 'restricted' &&
71
71
  profile.network.kind === 'restricted');
72
72
  }
73
- probe(request) {
74
- const plan = this.plan(request);
75
- if (!plan.ok)
76
- return plan;
77
- return {
78
- ok: true,
79
- executable: this.options.clientPath,
80
- sandboxType: 'windows',
81
- requiresSandbox: true,
82
- preference: plan.preference,
83
- };
84
- }
85
73
  transform(request) {
86
74
  const plan = this.plan(request);
87
75
  if (!plan.ok)
@@ -26,9 +26,9 @@
26
26
  // the model is trapped writing `dir /s /b` style commands. This module detects
27
27
  // a better shell (pwsh > powershell > cmd) and carries the result to the two
28
28
  // places that need it: the spawn call (shell-exec / shell-run-manager) and the
29
- // prompt surfaces that must DECLARE the dialect to the model (tool description,
30
- // session environment fragment). Selection without declaration — or the other
31
- // way round — makes the model guess the dialect, which is the original bug.
29
+ // Bash tool description that declares the dialect to the model. Selection
30
+ // without declaration — or the other way round — makes the model guess the
31
+ // dialect, which is the original bug.
32
32
  import { execFile } from 'node:child_process';
33
33
  import { existsSync } from 'node:fs';
34
34
  import { win32 } from 'node:path';
@@ -87,10 +87,6 @@ export function throwIfShellSetupFailed(shell) {
87
87
  if (shell.setupError)
88
88
  throw shell.setupError;
89
89
  }
90
- /** Model-facing shell name; a broken preference is declared, not silently hidden. */
91
- export function turnShellDisplayName(shell) {
92
- return shell.setupError ? `Unavailable (${shell.setupError.message})` : shell.plan.displayName;
93
- }
94
90
  /** Rejects a persisted override unless the Host can execute it as GNU Bash. */
95
91
  export async function validateShellPreference(settings, input = {}) {
96
92
  const plan = resolveShellPlan(settings, input);
@@ -32,7 +32,6 @@ export const DEFAULT_MAX_LIVE_PTY_RUNS = 8;
32
32
  export const DEFAULT_SHELL_RUN_FLUSH_INTERVAL_MS = 1_000;
33
33
  export const DEFAULT_SHELL_RUN_FLUSH_BYTES = 64 * 1024;
34
34
  export const DEFAULT_PIPE_OUTPUT_DRAIN_MS = 2_000;
35
- export const SHELL_RUN_CONTEXT_SUMMARY_LIMIT = 8;
36
35
  export const SHELL_RUN_RESOURCE_PREFIX = 'maka://runtime/background-tasks';
37
36
  export const MAX_SHELL_RUN_RESOURCE_REF_CHARS = SHELL_RUN_RESOURCE_PREFIX.length + 1 + SHELL_RUN_ID_MAX_CHARS;
38
37
  export { isWellFormedTerminalInput };
@@ -30,7 +30,7 @@ import { PipeTailCollector } from './pipe-tail-collector.js';
30
30
  import { PtyProcessDriver } from './pty-process-driver.js';
31
31
  import { PTY_INITIAL_COLS, PTY_INITIAL_ROWS, PtyScreenCollector, } from './pty-screen-collector.js';
32
32
  import { loadPtyStack } from './pty-stack.js';
33
- import { DEFAULT_BASH_TIMEOUT_MS, DEFAULT_MAX_LIVE_PTY_RUNS, DEFAULT_MAX_LIVE_SHELL_RUNS, DEFAULT_PIPE_OUTPUT_DRAIN_MS, DEFAULT_SHELL_RUN_FLUSH_BYTES, DEFAULT_SHELL_RUN_FLUSH_INTERVAL_MS, MAX_FOREGROUND_BASH_TIMEOUT_MS, MAX_SHELL_RUN_TIMEOUT_MS, SHELL_RUN_CONTEXT_SUMMARY_LIMIT, ShellRunPtyControlClosedError, parseShellRunResourceRef, shellRunResourceRef, validateWriteStdinInput, } from './shell-run-contract.js';
33
+ import { DEFAULT_BASH_TIMEOUT_MS, DEFAULT_MAX_LIVE_PTY_RUNS, DEFAULT_MAX_LIVE_SHELL_RUNS, DEFAULT_PIPE_OUTPUT_DRAIN_MS, DEFAULT_SHELL_RUN_FLUSH_BYTES, DEFAULT_SHELL_RUN_FLUSH_INTERVAL_MS, MAX_FOREGROUND_BASH_TIMEOUT_MS, MAX_SHELL_RUN_TIMEOUT_MS, ShellRunPtyControlClosedError, parseShellRunResourceRef, shellRunResourceRef, validateWriteStdinInput, } from './shell-run-contract.js';
34
34
  import { compactShellRunContent, ptyControlOperation, shellRunContent, shellRunUpdate, terminalContent, } from './shell-run-tool-result.js';
35
35
  import { CompletionLatch } from './completion-latch.js';
36
36
  import { closeChildFdSources } from './child-fd-input.js';
@@ -404,30 +404,6 @@ export class ShellRunProcessManager {
404
404
  const record = await this.markObserved(await live.finished.join());
405
405
  return shellRunContent(record, { kind: 'stop', applied });
406
406
  }
407
- async buildContextSummary(sessionId) {
408
- const records = (await this.actionableRecords(sessionId)).filter((record) => record.visibility !== 'user');
409
- if (records.length === 0)
410
- return undefined;
411
- const visible = records.slice(0, SHELL_RUN_CONTEXT_SUMMARY_LIMIT);
412
- const lines = [
413
- 'Background tasks for this session:',
414
- ...visible.map((record) => {
415
- const completed = record.completedAt !== undefined ? ` completedAt=${record.completedAt}` : '';
416
- return `- ref=${shellRunResourceRef(record.shellRunId)} mode=${record.output.mode} status=${record.status} cwd=${record.cwd} updatedAt=${record.updatedAt}${completed} command=${JSON.stringify(record.command)}`;
417
- }),
418
- ];
419
- const overflow = records.length - visible.length;
420
- if (overflow > 0)
421
- lines.push(`- ${overflow} more background task(s) not shown in this turn tail.`);
422
- const hasControllablePty = records.some((record) => {
423
- const live = this.liveResource(sessionId, record.shellRunId);
424
- return live?.mode === 'pty' && isPtyControlOpen(live);
425
- });
426
- lines.push(hasControllablePty
427
- ? 'Use Read on a ref for its bounded output snapshot; use WriteStdin to control a running PTY task.'
428
- : 'Use Read on a ref for its bounded output snapshot.');
429
- return lines.join('\n');
430
- }
431
407
  async listSessionUpdates(sessionId) {
432
408
  const records = await this.input.store.listSessionShellRuns(sessionId);
433
409
  return records.map(shellRunUpdate);
@@ -1483,13 +1459,6 @@ export class ShellRunProcessManager {
1483
1459
  return this.input.store.updateShellRun(current.sessionId, current.shellRunId, buildPatch());
1484
1460
  }
1485
1461
  }
1486
- async actionableRecords(sessionId) {
1487
- const records = await this.input.store.listSessionShellRuns(sessionId);
1488
- return records
1489
- .filter((record) => isActiveShellRunStatus(record.status) ||
1490
- (record.observedAt === undefined && isTerminalShellRunStatus(record.status)))
1491
- .sort(compareActionableShellRuns);
1492
- }
1493
1462
  notifyShellRunUpdate(record) {
1494
1463
  try {
1495
1464
  this.input.onShellRunUpdate?.(shellRunUpdate(record));
@@ -1679,13 +1648,6 @@ function startupCleanupError(startupError, cleanupFailure) {
1679
1648
  const cleanupError = asError(cleanupFailure, 'Shell process startup cleanup failed');
1680
1649
  return new Error(`Shell process startup failed: ${safeFailureMessage(startupError)}; startup cleanup failed: ${safeFailureMessage(cleanupError)}`, { cause: new AggregateError([startupError, cleanupError]) });
1681
1650
  }
1682
- function compareActionableShellRuns(a, b) {
1683
- const rank = (record) => (isActiveShellRunStatus(record.status) ? 1 : 0);
1684
- return (rank(a) - rank(b) ||
1685
- b.updatedAt - a.updatedAt ||
1686
- b.startedAt - a.startedAt ||
1687
- a.shellRunId.localeCompare(b.shellRunId));
1688
- }
1689
1651
  async function racePromiseWithAbort(promise, signal) {
1690
1652
  if (!signal)
1691
1653
  return promise;
@@ -211,7 +211,7 @@ export function buildStopBackgroundTaskTool(backgroundTasks) {
211
211
  return {
212
212
  name: 'StopBackgroundTask',
213
213
  activityKind: 'command',
214
- description: 'Stop a background task by runtime ref. Currently supports background shell run refs returned by Bash and shown in the turn tail.',
214
+ description: 'Stop a background task by runtime ref. Currently supports background shell run refs returned by Bash.',
215
215
  parameters: z.object({
216
216
  ref: z
217
217
  .string()
@@ -34,8 +34,8 @@ function buildTaskCreateTool(store, name, updateToolName) {
34
34
  return {
35
35
  name,
36
36
  displayName: 'Task Create',
37
- description: 'Add one or more tasks to the session task ledger. The full updated ledger is re-shown each turn, ' +
38
- `so use this to record work you plan to do; update status with ${updateToolName} as you progress.`,
37
+ description: 'Add one or more tasks to the session task ledger. ' +
38
+ `Use task_list or task_get to read it later, and update status with ${updateToolName} as you progress.`,
39
39
  parameters: z.object({
40
40
  tasks: z
41
41
  .array(z.object({
@@ -96,7 +96,6 @@
96
96
  "./system-prompt/main-session-prompt": "./dist/system-prompt/main-session-prompt.js",
97
97
  "./system-prompt/personalization-prompt": "./dist/system-prompt/personalization-prompt.js",
98
98
  "./system-prompt/project-context": "./dist/system-prompt/project-context.js",
99
- "./system-prompt/session-environment-prompt": "./dist/system-prompt/session-environment-prompt.js",
100
99
  "./system-prompt/workspace-instructions": "./dist/system-prompt/workspace-instructions.js",
101
100
  "./task-ledger-tools": "./dist/task-ledger-tools.js",
102
101
  "./tavily-search": "./dist/tavily-search.js",
@@ -32,7 +32,7 @@ import { buildHistoryTools } from '@maka/runtime/history-tools';
32
32
  import { createLocalContinuationSafetyInspector } from '@maka/runtime/continuation-safety';
33
33
  import { createConfiguredSubagentCatalog } from '@maka/runtime/configured-subagent-catalog';
34
34
  import { buildHostCapabilitiesFromBinding } from '@maka/runtime/skills';
35
- import { createBuiltinSandboxManager, createSandboxDiagnosticsProvider, isBuiltinFilesystemWorkerSandboxAvailable, } from '@maka/runtime/sandbox';
35
+ import { createBuiltinSandboxManager, isBuiltinFilesystemWorkerSandboxAvailable, } from '@maka/runtime/sandbox';
36
36
  import { createFilesystemWorkerLaunchSpecProvider, FilesystemWorkerClient, } from '@maka/runtime/filesystem-worker';
37
37
  import { isOAuthEnrollmentProviderEnabled } from '@maka/runtime/oauth-provider-contracts';
38
38
  import { loadHistoryCompactCheckpointsFromRunLedger, loadLatestHistoryCompactCheckpointFromRunLedger, } from '@maka/runtime/history-compact-ledger';
@@ -224,12 +224,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
224
224
  resourceLocation: { kind: 'runtime' },
225
225
  })
226
226
  : undefined;
227
- const sandboxDiagnostics = createSandboxDiagnosticsProvider({
228
- ...(sandboxManager ? { sandboxManager } : {}),
229
- ...(filesystemWorkerLaunchSpecProvider
230
- ? { getFilesystemWorkerLaunchSpec: filesystemWorkerLaunchSpecProvider }
231
- : {}),
232
- });
233
227
  const filesystemWorker = sandboxManager && filesystemWorkerLaunchSpecProvider
234
228
  ? new FilesystemWorkerClient({
235
229
  sandboxManager,
@@ -478,7 +472,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
478
472
  context: backendContext,
479
473
  runtimePolicy: runtimePolicyStores,
480
474
  oauthCredentials,
481
- sandboxDiagnostics,
482
475
  createRunComposer: createInteractiveRunComposerFactory({
483
476
  skills,
484
477
  memory: requireMemory(memory),
@@ -195,9 +195,7 @@ export async function createHostAiSdkBackend(input) {
195
195
  const resolved = await modelComposition.resolveSystemPrompt({
196
196
  sessionId: input.context.sessionId,
197
197
  turnId: context.turnId,
198
- ...(context.runId ? { runId: context.runId } : {}),
199
198
  cwd: input.context.header.cwd,
200
- workspaceRoot: input.context.workspaceRoot,
201
199
  ...(context.emitSkillCatalogTrace
202
200
  ? { emitSkillCatalogTrace: context.emitSkillCatalogTrace }
203
201
  : {}),
@@ -239,7 +237,6 @@ export async function createHostAiSdkBackend(input) {
239
237
  appendMessage: input.context.appendMessage ??
240
238
  ((message) => input.context.store.appendMessage(input.context.sessionId, message)),
241
239
  readExecutionBoundary: () => input.context.store.readExecutionBoundary(input.context.sessionId),
242
- sandboxDiagnostics: input.sandboxDiagnostics,
243
240
  ...(input.context.store.createSandboxBoundaryRequest
244
241
  ? {
245
242
  createSandboxBoundaryRequest: (request) => input.context.store.createSandboxBoundaryRequest(request),
@@ -307,15 +304,12 @@ export async function createHostAiSdkBackend(input) {
307
304
  systemPrompt: async (context) => {
308
305
  const resolved = await resolveRunPrompt({
309
306
  turnId: context.turnId,
310
- ...(context.runId ? { runId: context.runId } : {}),
311
307
  ...(context.emitSkillCatalogTrace
312
308
  ? { emitSkillCatalogTrace: context.emitSkillCatalogTrace }
313
309
  : {}),
314
310
  });
315
311
  return resolved.text;
316
312
  },
317
- turnTailPrompt: modelComposition.turnTailPrompt,
318
- shellRunContextSummary: input.context.shellRunContextSummary,
319
313
  lookupPricing: pricing,
320
314
  recordModelCallAttempt,
321
315
  assertModelCallAccountingReady,
@@ -19,7 +19,6 @@
19
19
  import { buildSideConversationSystemPromptFragment, isSideConversationSession, } from '@maka/core/side-conversation';
20
20
  import { buildDeepResearchSystemPromptFragment, isDeepResearchSession, } from '@maka/core/deep-research';
21
21
  import { activePlanExecution } from '@maka/core/plan';
22
- import { filterModelVisibleTaskLedgerTasks, renderTaskLedgerPromptText, } from '@maka/core/task-ledger';
23
22
  import { assembleMainSessionSystemPrompt } from '@maka/runtime/system-prompt/main-session-prompt';
24
23
  import { buildAskUserQuestionTool } from '@maka/runtime/ask-user-question-tool';
25
24
  import { buildBuiltinTools } from '@maka/runtime/builtin-tools';
@@ -27,17 +26,15 @@ import { buildCancelPlanTool, buildSubmitPlanTool, buildUpdatePlanTool, } from '
27
26
  import { buildParentAgentTools } from '@maka/runtime/subagent-tools';
28
27
  import { buildPersonalizationPromptFragment } from '@maka/runtime/system-prompt/personalization-prompt';
29
28
  import { buildRequestSandboxBoundaryTool } from '@maka/runtime/sandbox-boundary-tool';
30
- import { buildSessionEnvironmentPromptFragment } from '@maka/runtime/system-prompt/session-environment-prompt';
31
29
  import { buildHostCapabilitiesFromBinding, buildSkillAgentToolFromInventory, buildSkillSearchAgentToolFromInventory, buildSkillsPromptFragmentFromInventoryWithReport, SkillShadowSelectionTracker, } from '@maka/runtime/skills';
32
30
  import { buildTaskLedgerTools } from '@maka/runtime/task-ledger-tools';
33
31
  import { buildWorkspaceInstructionsPromptFragment } from '@maka/runtime/system-prompt/workspace-instructions';
34
32
  import { isDeepResearchToolAllowed } from '@maka/runtime/deep-research-tools';
35
33
  import { listRunnableBuiltinAgentDefinitions } from '@maka/runtime/agent-catalog';
36
- import { renderInterruptedPlanContext, renderPlanExecutionPrompt, renderPlanModePrompt, selectCollaborationTools, } from '@maka/runtime/plan-mode';
37
- import { resolveProjectGitInfo } from '@maka/runtime/system-prompt/project-context';
34
+ import { renderPlanModePrompt, selectCollaborationTools } from '@maka/runtime/plan-mode';
38
35
  import { routeWebFetchTools } from '@maka/runtime/web-fetch-tool';
39
36
  import { routeWebSearchTools } from '@maka/runtime/native-web-search-tool';
40
- import { resolveTurnShellPlan, turnShellDisplayName, } from '@maka/runtime/shell-detect';
37
+ import { resolveTurnShellPlan } from '@maka/runtime/shell-detect';
41
38
  import { readDuringBackendCreation } from './execution-model-authority.js';
42
39
  import { hostedExecutionRunProfile, projectHostedExecutionTools, } from './hosted-execution-tool-profile.js';
43
40
  import { shouldResolveHostTavilyWebSearchReadiness } from './web-search-tool.js';
@@ -165,26 +162,6 @@ export function createInteractiveRunComposer(input) {
165
162
  tools,
166
163
  toolAvailability,
167
164
  resolveSystemPrompt,
168
- turnTailPrompt: async (context) => {
169
- const environment = buildSessionEnvironmentPromptFragment({
170
- cwd: context.cwd,
171
- projectGit: await resolveProjectGitInfo(context.cwd),
172
- ...(input.platform ? { platform: input.platform } : {}),
173
- ...(input.shell ? { shell: turnShellDisplayName(input.shell) } : {}),
174
- ...(input.now ? { now: input.now() } : {}),
175
- });
176
- const tasks = filterModelVisibleTaskLedgerTasks(await input.taskLedger.list(context.sessionId, {
177
- classifyResumeTrust: true,
178
- includeArchived: false,
179
- }));
180
- return (joinFragments([
181
- environment,
182
- renderTaskLedgerTail(tasks),
183
- input.plan
184
- ? renderPlanTail(input.plan.state, input.plan.mode, input.plan.permissionMode === 'bypass')
185
- : undefined,
186
- ]) ?? environment);
187
- },
188
165
  });
189
166
  }
190
167
  /** Routes every model-visible tool surface through the same policy and readiness snapshot. */
@@ -372,21 +349,6 @@ function requireDeepResearchTools(tools) {
372
349
  throw new Error('Runtime Host Deep Research tools are not composed');
373
350
  return tools;
374
351
  }
375
- function renderPlanTail(state, mode, fullAccess) {
376
- const active = activePlanExecution(state);
377
- const execution = active ??
378
- (mode === 'plan'
379
- ? [...state.executions].reverse().find((candidate) => candidate.status === 'interrupted')
380
- : undefined);
381
- if (!execution)
382
- return undefined;
383
- const proposal = state.proposals.find((candidate) => candidate.proposalId === execution.proposalId);
384
- if (!proposal)
385
- return undefined;
386
- return active
387
- ? renderPlanExecutionPrompt({ proposal, execution: active })
388
- : renderInterruptedPlanContext({ proposal, execution, fullAccess });
389
- }
390
352
  function filterToolGroups(groups, names) {
391
353
  const seenIds = new Set();
392
354
  return groups.flatMap((group) => {
@@ -472,24 +434,6 @@ function renderMemoryPrompt(body) {
472
434
  '</local-memory>',
473
435
  ].join('\n');
474
436
  }
475
- function renderTaskLedgerTail(tasks) {
476
- if (tasks.length === 0)
477
- return undefined;
478
- const rendered = renderTaskLedgerPromptText(tasks);
479
- if (!rendered.text)
480
- return undefined;
481
- return [
482
- 'Current task ledger (current-turn context only; maintain it with task_create, task_update, task_list, and task_get — activate them via tool_search first when they are not already visible):',
483
- '<task-ledger>',
484
- rendered.text,
485
- ...(rendered.omittedCount > 0
486
- ? [
487
- `omitted=${rendered.omittedCount} (use task_list/task_get via tool_search for the complete ledger)`,
488
- ]
489
- : []),
490
- '</task-ledger>',
491
- ].join('\n');
492
- }
493
437
  function joinFragments(fragments) {
494
438
  const present = fragments
495
439
  .map((fragment) => fragment?.trim())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maka-agent",
3
- "version": "0.2.0-dev.6.20260830",
3
+ "version": "0.2.0-dev.8.20260830",
4
4
  "description": "Apache Maka (Incubating) developer snapshot; not an Apache release.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1,285 +0,0 @@
1
- /*
2
- * Licensed to the Apache Software Foundation (ASF) under one
3
- * or more contributor license agreements. See the NOTICE file
4
- * distributed with this work for additional information
5
- * regarding copyright ownership. The ASF licenses this file
6
- * to you under the Apache License, Version 2.0 (the
7
- * "License"); you may not use this file except in compliance
8
- * with the License. You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing,
13
- * software distributed under the License is distributed on an
14
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- * KIND, either express or implied. See the License for the
16
- * specific language governing permissions and limitations
17
- * under the License.
18
- */
19
- import { constants } from 'node:fs';
20
- import { access, realpath } from 'node:fs/promises';
21
- import { tmpdir } from 'node:os';
22
- import { resolve } from 'node:path';
23
- import { compilePermissionProfile } from '@maka/core/permission-profile-compiler';
24
- export function createSandboxDiagnosticsProvider(input) {
25
- return {
26
- resolve: async (request) => {
27
- const canonicalize = input.canonicalizePath ?? canonicalPath;
28
- const cwd = await canonicalize(request.cwd);
29
- const workspaceRoots = await Promise.all((request.workspaceRoots ?? [cwd]).map(canonicalize));
30
- const compiled = request.permissionProfile
31
- ? { profile: request.permissionProfile, workspaceRoots }
32
- : compilePermissionProfile({ mode: request.mode, cwd, workspaceRoots });
33
- const platform = input.platform ?? process.platform;
34
- const capabilityInput = {
35
- profile: compiled.profile,
36
- cwd,
37
- workspaceRoots: compiled.workspaceRoots,
38
- platform,
39
- sandboxManager: input.sandboxManager,
40
- isExecutable: input.isExecutable ?? defaultIsExecutable,
41
- };
42
- const command = await probeCommandCapability(capabilityInput);
43
- const filesystem = await probeFilesystemCapability({
44
- ...capabilityInput,
45
- getLaunchSpec: input.getFilesystemWorkerLaunchSpec,
46
- });
47
- return {
48
- schemaVersion: 1,
49
- platform,
50
- profile: {
51
- name: profileName(compiled.profile),
52
- type: compiled.profile.type,
53
- fileSystem: summarizeFileSystem(compiled.profile),
54
- network: summarizeNetwork(compiled.profile),
55
- cwd,
56
- workspaceRoots: [...new Set(compiled.workspaceRoots)],
57
- protectedMetadata: protectedMetadataNames(compiled.profile),
58
- },
59
- capabilities: { command, filesystem },
60
- };
61
- },
62
- };
63
- }
64
- export function toSandboxRunTraceProjection(snapshot) {
65
- return {
66
- schemaVersion: snapshot.schemaVersion,
67
- platform: snapshot.platform,
68
- profile: {
69
- name: snapshot.profile.name,
70
- type: snapshot.profile.type,
71
- fileSystem: snapshot.profile.fileSystem,
72
- network: snapshot.profile.network,
73
- protectedMetadata: [...snapshot.profile.protectedMetadata],
74
- },
75
- capabilities: {
76
- command: cloneCapability(snapshot.capabilities.command),
77
- filesystem: cloneCapability(snapshot.capabilities.filesystem),
78
- },
79
- };
80
- }
81
- async function probeCommandCapability(input) {
82
- const passive = passiveCapability(input.profile);
83
- if (passive)
84
- return passive;
85
- const manager = input.sandboxManager;
86
- if (!manager) {
87
- return unavailable(expectedSandboxType(input.platform), 'selection', input.platform === 'darwin' || input.platform === 'linux' || input.platform === 'win32'
88
- ? 'backend_not_available'
89
- : 'unsupported_platform');
90
- }
91
- const selection = manager.selectInitial({ profile: input.profile, platform: input.platform });
92
- if (!selection.ok) {
93
- return unavailable(selection.sandboxType ?? expectedSandboxType(input.platform), 'selection', selection.reason);
94
- }
95
- if (selection.sandboxType === 'none') {
96
- return {
97
- status: 'not_required',
98
- backend: 'none',
99
- selectionReason: selection.reason,
100
- };
101
- }
102
- // The Windows broker runs the purpose-built filesystem worker, but cannot
103
- // launch an arbitrary shell inside its capability-less AppContainer. Match
104
- // the real Bash execution contract instead of reporting the broker itself as
105
- // evidence that command sandboxing is available.
106
- if (input.platform === 'win32') {
107
- return unavailable('windows', 'capability', 'backend_not_implemented', selection.reason);
108
- }
109
- try {
110
- const probed = manager.probe({
111
- platform: input.platform,
112
- command: {
113
- program: '/bin/sh',
114
- args: ['-c', 'true'],
115
- cwd: input.cwd,
116
- env: {},
117
- profile: input.profile,
118
- pathContext: {
119
- workspaceRoots: input.workspaceRoots,
120
- tmpdir: await canonicalPath(tmpdir()),
121
- ...(input.platform === 'win32' ? {} : { slashTmp: await canonicalPath('/tmp') }),
122
- },
123
- },
124
- });
125
- if (!probed.ok) {
126
- return unavailable(probed.sandboxType ?? selection.sandboxType, 'transform', probed.reason, selection.reason);
127
- }
128
- const executable = probed.executable;
129
- if (!executable || !(await safelyCheckExecutable(executable, input.isExecutable))) {
130
- return unavailable(probed.sandboxType, 'capability', 'executable_unavailable', selection.reason);
131
- }
132
- return {
133
- status: 'available',
134
- backend: probed.sandboxType,
135
- selectionReason: selection.reason,
136
- };
137
- }
138
- catch {
139
- return unavailable(selection.sandboxType, 'capability', 'capability_probe_failed', selection.reason);
140
- }
141
- }
142
- async function probeFilesystemCapability(input) {
143
- const passive = passiveCapability(input.profile);
144
- if (passive)
145
- return passive;
146
- if (!input.sandboxManager) {
147
- return unavailable(expectedSandboxType(input.platform), 'selection', 'backend_not_available');
148
- }
149
- const selection = input.sandboxManager.selectInitial({
150
- profile: input.profile,
151
- platform: input.platform,
152
- });
153
- if (!selection.ok) {
154
- return unavailable(selection.sandboxType ?? expectedSandboxType(input.platform), 'selection', selection.reason);
155
- }
156
- if (!input.getLaunchSpec) {
157
- return unavailable(selection.sandboxType, 'launch', 'filesystem_worker_unavailable', selection.reason);
158
- }
159
- let launch;
160
- try {
161
- launch = await input.getLaunchSpec();
162
- }
163
- catch {
164
- return unavailable(selection.sandboxType, 'capability', 'capability_probe_failed', selection.reason);
165
- }
166
- if (!launch.ok) {
167
- return unavailable(selection.sandboxType, 'launch', launch.reason, selection.reason);
168
- }
169
- try {
170
- const probed = input.sandboxManager.probe({
171
- platform: input.platform,
172
- command: {
173
- program: launch.spec.program,
174
- args: launch.spec.args,
175
- cwd: input.cwd,
176
- env: launch.spec.env,
177
- profile: input.profile,
178
- pathContext: {
179
- workspaceRoots: input.workspaceRoots,
180
- tmpdir: await canonicalPath(tmpdir()),
181
- ...(input.platform === 'win32' ? {} : { slashTmp: await canonicalPath('/tmp') }),
182
- runtimeReadableRoots: launch.spec.runtimeReadableRoots,
183
- executableRoots: launch.spec.executableRoots,
184
- },
185
- },
186
- });
187
- if (!probed.ok) {
188
- return unavailable(probed.sandboxType ?? selection.sandboxType, 'transform', probed.reason, selection.reason);
189
- }
190
- const executable = probed.executable;
191
- if (!executable || !(await safelyCheckExecutable(executable, input.isExecutable))) {
192
- return unavailable(probed.sandboxType, 'capability', 'executable_unavailable', selection.reason);
193
- }
194
- return {
195
- status: 'available',
196
- backend: probed.sandboxType,
197
- selectionReason: selection.reason,
198
- };
199
- }
200
- catch {
201
- return unavailable(selection.sandboxType, 'capability', 'capability_probe_failed', selection.reason);
202
- }
203
- }
204
- function passiveCapability(profile) {
205
- if (profile.type === 'external')
206
- return { status: 'external', backend: 'none' };
207
- if (profile.type === 'disabled' ||
208
- (profile.type === 'managed' && profile.fileSystem.kind !== 'restricted')) {
209
- return {
210
- status: 'not_required',
211
- backend: 'none',
212
- selectionReason: 'sandbox_not_required',
213
- };
214
- }
215
- return undefined;
216
- }
217
- function unavailable(backend, stage, reason, selectionReason) {
218
- return {
219
- status: 'unavailable',
220
- backend,
221
- ...(selectionReason ? { selectionReason } : {}),
222
- failure: { stage, reason },
223
- };
224
- }
225
- function expectedSandboxType(platform) {
226
- if (platform === 'darwin')
227
- return 'macos-seatbelt';
228
- if (platform === 'linux')
229
- return 'linux';
230
- if (platform === 'win32')
231
- return 'windows';
232
- return 'none';
233
- }
234
- function profileName(profile) {
235
- return profile.name ?? profile.type;
236
- }
237
- function summarizeFileSystem(profile) {
238
- if (profile.type === 'disabled')
239
- return 'disabled';
240
- if (profile.type === 'external')
241
- return 'external';
242
- if (profile.fileSystem.kind === 'unrestricted')
243
- return 'unrestricted';
244
- if (profile.fileSystem.kind === 'external_sandbox')
245
- return 'external';
246
- if (!profile.fileSystem.entries.some((entry) => entry.access === 'write'))
247
- return 'read-only';
248
- return profile.fileSystem.entries.some((entry) => entry.kind === 'special' && entry.special === ':workspace_roots' && entry.access === 'write')
249
- ? 'workspace-write'
250
- : 'custom-restricted';
251
- }
252
- function summarizeNetwork(profile) {
253
- return profile.type === 'disabled' ? 'unmanaged' : profile.network.kind;
254
- }
255
- function protectedMetadataNames(profile) {
256
- if (profile.type !== 'managed')
257
- return [];
258
- return [...(profile.fileSystem.protectedMetadata?.names ?? [])];
259
- }
260
- function cloneCapability(capability) {
261
- return {
262
- ...capability,
263
- ...(capability.failure ? { failure: { ...capability.failure } } : {}),
264
- };
265
- }
266
- async function safelyCheckExecutable(path, isExecutable) {
267
- try {
268
- return await isExecutable(path);
269
- }
270
- catch {
271
- return false;
272
- }
273
- }
274
- async function defaultIsExecutable(path) {
275
- try {
276
- await access(path, constants.X_OK);
277
- return true;
278
- }
279
- catch {
280
- return false;
281
- }
282
- }
283
- async function canonicalPath(path) {
284
- return await realpath(path).catch(() => resolve(path));
285
- }