@playcraft/cli 0.1.80 → 0.1.82

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.
@@ -94,29 +94,9 @@ export class WorkspaceModelBroker {
94
94
  activate: (readOnly = false) => {
95
95
  if (!this.valid(entry) || this.routes.get(routeKey) !== route)
96
96
  throw new Error('model_access_denied');
97
- const priorFeedback = route.selected?.feedback;
98
- let refsBlocked = Boolean(entry.refsBlocked || priorFeedback?.refsBlocked && priorFeedback.clientRequestId === clientRequestId);
99
- if (sessionId && clientRequestId) {
100
- const overlaps = (this.state.journal.listOperations?.() ?? []).some(({ operation }) => ['session.turn', 'session.review', 'session.compact'].includes(operation.kind)
101
- && ['dispatched', 'accepted', 'uncertain'].includes(operation.status)
102
- && operation.generation === this.state.config.generation && operation.runtimeEpoch === this.state.runtimeEpoch
103
- && (operation.sessionId !== sessionId || operation.clientRequestId !== clientRequestId));
104
- if (overlaps) {
105
- refsBlocked = true;
106
- // A completed overlapping turn may leave shells alive. Only a later turn gets a new safe boundary.
107
- for (const prepared of this.entries.values()) {
108
- if (prepared.epoch === this.state.runtimeEpoch)
109
- prepared.refsBlocked = true;
110
- }
111
- for (const existing of this.routes.values()) {
112
- if (existing.epoch === this.state.runtimeEpoch && existing.selected?.feedback)
113
- existing.selected.feedback.refsBlocked = true;
114
- }
115
- }
116
- }
117
97
  route.lastAdmissionReason = undefined;
118
98
  route.selected = { entry, model: credential.model,
119
- ...(sessionId && clientRequestId ? { feedback: { sessionId, clientRequestId, cwd, boundaryId, readOnly, refsBlocked,
99
+ ...(sessionId && clientRequestId ? { feedback: { sessionId, clientRequestId, cwd, boundaryId, readOnly,
120
100
  ...(originCwd ? { originCwd } : {}) } } : {}) };
121
101
  },
122
102
  model: credential.model,
@@ -1,3 +1,4 @@
1
+ import { join } from 'node:path';
1
2
  export const NATIVE_APPROVALS_REVIEWER = 'user';
2
3
  /** Trusted batch policy wins over the adapter-wide fixed policy. A browser mode may only narrow it. */
3
4
  export function resolveSessionExecution(cwd, mode, trusted, fixed) {
@@ -22,16 +23,22 @@ export function executionPolicy(cwd, mode, fixed) {
22
23
  networkAccess: false, excludeTmpdirEnvVar: true, excludeSlashTmp: true,
23
24
  } };
24
25
  }
25
- export function threadExecutionParams(execution) {
26
+ export function threadExecutionParams(execution, shellEnvironment = {}) {
26
27
  const sandbox = execution.sandboxPolicy.type === 'readOnly' ? 'read-only'
27
28
  : execution.sandboxPolicy.type === 'workspaceWrite' ? 'workspace-write' : 'danger-full-access';
28
29
  const policy = execution.sandboxPolicy;
30
+ const scratch = execution.scratchDir;
29
31
  return { cwd: execution.cwd, approvalPolicy: execution.approvalPolicy, approvalsReviewer: NATIVE_APPROVALS_REVIEWER, sandbox,
30
32
  config: policy.type === 'workspaceWrite' ? {
31
33
  'sandbox_workspace_write.writable_roots': policy.writableRoots,
32
34
  'sandbox_workspace_write.network_access': policy.networkAccess,
33
35
  'sandbox_workspace_write.exclude_tmpdir_env_var': policy.excludeTmpdirEnvVar,
34
36
  'sandbox_workspace_write.exclude_slash_tmp': policy.excludeSlashTmp,
37
+ ...(scratch ? { 'shell_environment_policy.set': {
38
+ ...shellEnvironment, TMPDIR: scratch, TMP: scratch, TEMP: scratch,
39
+ XDG_CONFIG_HOME: join(scratch, 'config'), XDG_CACHE_HOME: join(scratch, 'cache'),
40
+ ...(execution.chromiumPath ? { PLAYCRAFT_CHROMIUM_PATH: execution.chromiumPath } : {}),
41
+ } } : {}),
35
42
  } : {} };
36
43
  }
37
44
  export const APPROVAL_METHODS = new Set([
@@ -43,11 +43,12 @@ export class WorkspaceRemixReferencesBroker {
43
43
  .map((item) => item.operation)
44
44
  .filter((operation) => ['session.turn', 'session.review', 'session.compact'].includes(operation.kind) &&
45
45
  ACTIVE.has(operation.status) &&
46
+ operation.sessionId === context.sessionId &&
47
+ operation.clientRequestId === context.clientRequestId &&
46
48
  operation.generation === state.config.generation &&
47
49
  operation.runtimeEpoch === state.runtimeEpoch);
48
50
  const operation = operations.length === 1 ? operations[0] : undefined;
49
51
  if (!valid() ||
50
- context.refsBlocked ||
51
52
  state.journal.destroyed() ||
52
53
  !operation ||
53
54
  operation.kind !== 'session.turn' ||
@@ -24,7 +24,7 @@ export class WorkspaceSkillDiscoveryBroker {
24
24
  && operation.generation === state.config.generation && operation.runtimeEpoch === state.runtimeEpoch
25
25
  && ['dispatched', 'accepted'].includes(operation.status));
26
26
  const operation = operations.length === 1 ? operations[0] : undefined;
27
- if (!valid() || context.refsBlocked || state.journal.destroyed() || !operation?.workspaceId || !operation.directoryName
27
+ if (!valid() || state.journal.destroyed() || !operation?.workspaceId || !operation.directoryName
28
28
  || operation.directoryName === 'root' || !operation.nativeThreadId || !operation.nativeTurnId
29
29
  || !session || session.threadId !== operation.nativeThreadId || session.activeTurnId !== operation.nativeTurnId
30
30
  || session.cwd !== context.cwd || session.workspaceId !== operation.workspaceId
@@ -47,7 +47,7 @@ export async function createWorkspaceArchive(root, options = {}) {
47
47
  continue;
48
48
  const target = join(directory, entry.name);
49
49
  const path = relative(rootReal, target).split(sep).join('/');
50
- if (isCredentialFile(path) || /(?:^|\/)\.playcraft\/(?:workspace-context(?:\.[^/]*)?|video-replication)(?:\/|$)/.test(path))
50
+ if (isCredentialFile(path) || /(?:^|\/)\.playcraft\/(?:workspace-context(?:\.[^/]*)?|video-replication|apk-replication)(?:\/|$)/.test(path))
51
51
  continue;
52
52
  if (excludedRoots.some(excluded => inside(excluded, target)))
53
53
  continue;
@@ -18,6 +18,7 @@ export async function writeWorkspaceCliContext(root, workspaceId) {
18
18
  await rename(temporary, join(management, 'workspace-context.json'));
19
19
  await excludeFromGit(root, '/.playcraft/workspace-context.json');
20
20
  await excludeFromGit(root, '/.playcraft/video-replication/');
21
+ await excludeFromGit(root, '/.playcraft/apk-replication/');
21
22
  }
22
23
  finally {
23
24
  await rm(temporary, { force: true });
@@ -33,7 +33,7 @@ function gitEnvironment() {
33
33
  function excluded(path) {
34
34
  const parts = path.split('/');
35
35
  return parts.some(part => EXCLUDED.has(part.toLowerCase()) || /^\.playcraft-(?:credential|transfer)-.*\.tmp$/i.test(part)) ||
36
- parts.some((part, index) => part === '.playcraft' && /^(?:workspace-context(?:\..*)?|video-replication)$/.test(parts[index + 1] ?? '')) ||
36
+ parts.some((part, index) => part === '.playcraft' && /^(?:workspace-context(?:\..*)?|video-replication|apk-replication)$/.test(parts[index + 1] ?? '')) ||
37
37
  isCredentialFile(path);
38
38
  }
39
39
  export function transferGit(root, args) {
@@ -12,6 +12,7 @@ export const WORKSPACE_SHARED_PATHS = [
12
12
  '.playcraft/skills',
13
13
  '.playcraft/skill-artifacts',
14
14
  '.playcraft/video-replication',
15
+ '.playcraft/apk-replication',
15
16
  '.playcraft-temp',
16
17
  'dist',
17
18
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcraft/cli",
3
- "version": "0.1.80",
3
+ "version": "0.1.82",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -57,8 +57,8 @@
57
57
  "@gltf-transform/core": "^4.3.0",
58
58
  "@gltf-transform/extensions": "^4.3.0",
59
59
  "@gltf-transform/functions": "^4.3.0",
60
- "@playcraft/build": "0.1.80",
61
- "@playcraft/common": "0.1.80",
60
+ "@playcraft/build": "0.1.82",
61
+ "@playcraft/common": "0.1.82",
62
62
  "better-sqlite3-pinned": "npm:better-sqlite3@13.0.3",
63
63
  "chokidar": "^4.0.3",
64
64
  "commander": "^13.1.0",