praxis-agent 0.45.1 → 0.45.3

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.
@@ -2990,11 +2990,13 @@ export class ClaudeSessionService {
2990
2990
  let projectMemoryRecallMessages = [];
2991
2991
  let observeModelRequestUsage = () => undefined;
2992
2992
  const durableFollowUps = new DurableFollowUpTracker();
2993
+ const claimedToolCallIds = new Set();
2993
2994
  const observer = {
2994
2995
  ...(nativeLease
2995
2996
  ? {
2996
2997
  toolExecutionStarted: async (call) => {
2997
2998
  await nativeLease.beginToolExecution(call.id);
2999
+ claimedToolCallIds.add(call.id);
2998
3000
  },
2999
3001
  }
3000
3002
  : {}),
@@ -3087,6 +3089,10 @@ export class ClaudeSessionService {
3087
3089
  await refreshRuntimeContext();
3088
3090
  }
3089
3091
  if (nativeLease) {
3092
+ if (!claimedToolCallIds.has(call.id) && !signal?.aborted) {
3093
+ await nativeLease.beginToolExecution(call.id);
3094
+ claimedToolCallIds.add(call.id);
3095
+ }
3090
3096
  await nativeLease.appendToolCompletion({
3091
3097
  callId: call.id,
3092
3098
  result: toolResult,
@@ -3,7 +3,7 @@ import { join } from 'node:path';
3
3
  import { writeFileAtomically } from '../../platform/atomic-write.js';
4
4
  import { resolveDataPlaneRoot } from '../../persistence/data-plane.js';
5
5
  import { loadNativeSharedResources } from '../../persistence/native-resources.js';
6
- import { permissionRuleValueFromString, permissionRuleValueToString, } from '../../permissions/permission-updates.js';
6
+ import { permissionRuleStringIsValid, permissionRuleValueFromString, permissionRuleValueToString, } from '../../permissions/permission-updates.js';
7
7
  function isRecord(value) {
8
8
  return typeof value === 'object' && value !== null && !Array.isArray(value);
9
9
  }
@@ -60,7 +60,7 @@ async function sourceUnchanged(path, source) {
60
60
  }
61
61
  }
62
62
  export async function addTuiPermissionRule({ cwd, behavior, rule, scope, configRoot, }) {
63
- if (!/^([A-Za-z][\w-]*)(?:\(.*\))?$/u.test(rule))
63
+ if (!permissionRuleStringIsValid(rule))
64
64
  throw new Error(`Invalid permission rule: ${rule}`);
65
65
  const path = settingsPath(configRoot ?? configRootPath(), cwd, scope);
66
66
  for (let attempt = 0; attempt < 3; attempt += 1) {
@@ -10,7 +10,7 @@ import { shellPermissionMatchCandidates } from './bash-normalization.js';
10
10
  import { pathIsInsideRoots, validateBashPathSafety, } from './bash-path-safety.js';
11
11
  import { validateSedSafety } from './sed-safety.js';
12
12
  import { parseShellRule, shellRuleMatches } from './shell-rule-matching.js';
13
- import { effectiveAdditionalDirectories, effectivePermissionMode, filePermissionSuggestions, permissionRuleValueFromString, permissionRuleValueToString, shellInputIsReadOnly, shellPermissionSuggestions, shellSubcommands, skillPermissionSuggestions, } from './permission-updates.js';
13
+ import { effectiveAdditionalDirectories, effectivePermissionMode, filePermissionSuggestions, permissionRuleValueFromString, permissionRuleStringIsValid, permissionRuleValueToString, shellInputIsReadOnly, shellPermissionSuggestions, shellSubcommands, skillPermissionSuggestions, } from './permission-updates.js';
14
14
  const DEFAULT_BEHAVIOR = {
15
15
  Agent: 'allow',
16
16
  SendMessage: 'allow',
@@ -144,7 +144,7 @@ export function validateClaudePermissionSettings(settings) {
144
144
  throw new Error(`permissions.${field} must be an array of strings: ${resource.path}`);
145
145
  }
146
146
  for (const rule of rules) {
147
- if (!/^([A-Za-z][\w-]*)(?:\(.*\))?$/.test(rule)) {
147
+ if (!permissionRuleStringIsValid(rule)) {
148
148
  throw new Error(`Invalid permission rule in ${resource.path}: ${rule}`);
149
149
  }
150
150
  }
@@ -1,5 +1,6 @@
1
1
  import type { PermissionMode, PermissionRuleValue, PermissionUpdate } from '../core/runtime.js';
2
2
  export declare function permissionRuleValueToString(rule: PermissionRuleValue): string;
3
+ export declare function permissionRuleStringIsValid(value: string): boolean;
3
4
  export declare function permissionRuleValueFromString(value: string): PermissionRuleValue;
4
5
  export declare function parsePermissionUpdates(value: unknown): readonly PermissionUpdate[] | undefined;
5
6
  export declare function extractPermissionRules(updates: readonly PermissionUpdate[] | undefined): readonly PermissionRuleValue[];
@@ -10,6 +10,9 @@ export function permissionRuleValueToString(rule) {
10
10
  .replaceAll(')', '\\)');
11
11
  return `${rule.toolName}(${content})`;
12
12
  }
13
+ export function permissionRuleStringIsValid(value) {
14
+ return /^([A-Za-z][\w-]*)(?:\(.*\))?$/su.test(value);
15
+ }
13
16
  function unescapedIndex(value, character, fromEnd = false) {
14
17
  const start = fromEnd ? value.length - 1 : 0;
15
18
  const end = fromEnd ? -1 : value.length;
@@ -9,7 +9,7 @@ function workflowDefinition() {
9
9
  name: 'Workflow',
10
10
  description: `Run an explicitly requested, sandboxed JavaScript workflow in the background. Use only when the user asks for a workflow or named saved workflow; for ordinary delegation use Agent.
11
11
 
12
- Every script starts with a pure-literal \`export const meta = { name, description, phases? }\`. Its async body may use \`args\`, \`agent(prompt, options?)\`, \`parallel(thunks)\`, \`pipeline(items, ...stages)\`, \`workflow(nameOrScriptPath, args)\`, \`phase(title)\`, \`log(message)\`, and \`budget.{total,spent(),remaining()}\`. Agent options are \`label\`, \`phase\`, \`model\`, \`effort\`, \`agentType\`, \`schema\`, and \`isolation: 'worktree'\`. Pipeline stages receive \`(previousResult, originalItem, index)\`; failed parallel or pipeline items become null. Nested workflows are limited to one level.
12
+ Every script starts with a pure-literal \`export const meta = { name, description, phases? }\`. \`phases\` is optional and must be an array of objects shaped \`{ title: string, detail?: string, model?: string }\`, never an array of strings. Its async body may use \`args\`, \`agent(prompt, options?)\`, \`parallel(thunks)\`, \`pipeline(items, ...stages)\`, \`workflow(nameOrScriptPath, args)\`, \`phase(title)\`, \`log(message)\`, and \`budget.{total,spent(),remaining()}\`. Agent options are \`label\`, \`phase\`, \`model\`, \`effort\`, \`agentType\`, \`schema\`, and \`isolation: 'worktree'\`. Pipeline stages receive \`(previousResult, originalItem, index)\`; failed parallel or pipeline items become null. Nested workflows are limited to one level.
13
13
 
14
14
  Provide one source: \`scriptPath\` takes precedence over \`script\`, which takes precedence over \`name\`. Saved names resolve from project \`${projectDirectory}/workflows\`, then user workflows, followed by built-ins. The call returns a task ID immediately; use TaskOutput/TaskStop for lifecycle. Resume a terminal or interrupted run with its script path and \`resumeFromRunId\`; completed matching agents replay from journal. Workflows allow at most 1000 agents, 4096 collection items, and bounded concurrency. Scripts have no Node.js, filesystem, network, ambient time, or randomness.`,
15
15
  inputSchema: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praxis-agent",
3
- "version": "0.45.1",
3
+ "version": "0.45.3",
4
4
  "description": "Local-first, single-user general agent for the command line.",
5
5
  "license": "MIT",
6
6
  "author": "wuqisen",