@yeaft/webchat-agent 1.0.434 → 1.0.436

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/index.js CHANGED
@@ -13,6 +13,7 @@ import ctx from './context.js';
13
13
  import {
14
14
  getDefaultAgentName,
15
15
  getDefaultYeaftDir,
16
+ resolveAgentWorkDir,
16
17
  resolveRuntimeIdentity,
17
18
  getConfigPath,
18
19
  loadServiceConfig,
@@ -58,7 +59,7 @@ function loadConfig() {
58
59
  const defaults = {
59
60
  serverUrl: 'ws://localhost:3456',
60
61
  agentName: DEFAULT_AGENT_NAME,
61
- workDir: process.cwd(),
62
+ workDir: '',
62
63
  reconnectInterval: 5000,
63
64
  agentSecret: 'agent-shared-secret'
64
65
  };
@@ -116,12 +117,23 @@ try {
116
117
  const agentSecret = process.env.AGENT_SECRET_FILE
117
118
  ? readFileSync(process.env.AGENT_SECRET_FILE, 'utf8').trim()
118
119
  : (process.env.AGENT_SECRET || fileConfig.agentSecret);
120
+ const WORK_DIR = resolveAgentWorkDir(fileConfig, process.env, AGENT_NAME);
121
+ if (!process.env.WORK_DIR && !fileConfig.workDir) {
122
+ try {
123
+ if (!existsSync(WORK_DIR)) {
124
+ mkdirSync(WORK_DIR, { recursive: true, mode: 0o700 });
125
+ console.log(`[Agent] Created default work dir: ${WORK_DIR}`);
126
+ }
127
+ } catch (err) {
128
+ console.warn(`[Agent] Could not ensure default work dir ${WORK_DIR}: ${err?.message || err}`);
129
+ }
130
+ }
119
131
 
120
132
  const CONFIG = {
121
133
  instanceId: INSTANCE_ID,
122
134
  serverUrl: process.env.SERVER_URL || fileConfig.serverUrl,
123
135
  agentName: AGENT_NAME,
124
- workDir: process.env.WORK_DIR || fileConfig.workDir || process.cwd(),
136
+ workDir: WORK_DIR,
125
137
  yeaftDir: YEAFT_DIR,
126
138
  telemetry: loadYeaftConfig({ dir: YEAFT_DIR }).telemetry,
127
139
  reconnectInterval: fileConfig.reconnectInterval,
@@ -234,6 +234,12 @@ export async function handleClientBrowser(client, msg, checkAgentAccess) {
234
234
  connectionGeneration: peer.connectionGeneration,
235
235
  };
236
236
  try {
237
+ // Commit the Web endpoint's scoped ICE credentials before the Agent can
238
+ // synchronously answer `browser_peer_prepare`. Otherwise a fast Agent
239
+ // may produce `browser_peer_prepared` while this field is still unset,
240
+ // causing the Web RTCPeerConnection to be created with no ICE servers.
241
+ peer.webIceServers = mintBrowserIceServers({ ...commonScope, endpointRole: 'web' });
242
+ peer.state = 'preparing';
237
243
  await sendToAgent(agent, {
238
244
  type: 'browser_peer_prepare',
239
245
  agentId,
@@ -247,8 +253,6 @@ export async function handleClientBrowser(client, msg, checkAgentAccess) {
247
253
  iceTransportPolicy: CONFIG.browserRuntime.iceTransportPolicy,
248
254
  agentIceServers: mintBrowserIceServers({ ...commonScope, endpointRole: 'agent' }),
249
255
  });
250
- peer.webIceServers = mintBrowserIceServers({ ...commonScope, endpointRole: 'web' });
251
- peer.state = 'preparing';
252
256
  } catch (error) {
253
257
  deleteBrowserPeer(peer.peerId);
254
258
  return fail(client, msg, 'browser_peer_prepare_failed', String(error?.message || error).slice(0, 500));
@@ -1 +1 @@
1
- {"version":"1.0.434"}
1
+ {"version":"1.0.436"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.434",
3
+ "version": "1.0.436",
4
4
  "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/service/config.js CHANGED
@@ -10,10 +10,18 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
10
10
  export const SERVICE_NAME = 'yeaft-agent';
11
11
  export const DEFAULT_INSTANCE_ID = 'default';
12
12
 
13
+ function assertSafeIdentitySegment(value, label) {
14
+ const normalized = String(value ?? '').trim();
15
+ if (normalized === '.' || normalized === '..') {
16
+ throw new Error(`${label} may not be "." or ".."`);
17
+ }
18
+ return normalized;
19
+ }
20
+
13
21
  export function getDefaultAgentName(machineName = hostname()) {
14
22
  const raw = String(machineName || '');
15
23
  if (!raw) return DEFAULT_INSTANCE_ID;
16
- return raw.replace(/[^A-Za-z0-9._-]/gu, '-');
24
+ return assertSafeIdentitySegment(raw.replace(/[^A-Za-z0-9._-]/gu, '-'), 'Agent name');
17
25
  }
18
26
 
19
27
  /**
@@ -57,7 +65,7 @@ export function isDefaultInstance(instanceId) {
57
65
  }
58
66
 
59
67
  export function validateInstanceId(instanceId) {
60
- const normalized = normalizeInstanceId(instanceId);
68
+ const normalized = assertSafeIdentitySegment(normalizeInstanceId(instanceId), 'Instance id');
61
69
  if (!/^[A-Za-z0-9_.-]+$/.test(normalized)) {
62
70
  throw new Error('Instance id may only contain letters, numbers, dot, underscore, or dash');
63
71
  }
@@ -86,10 +94,11 @@ function readIdentityArgs(args = []) {
86
94
 
87
95
  export function resolveDisplayName(args = [], env = process.env, fallbackName = getDefaultAgentName()) {
88
96
  const { explicitName } = readIdentityArgs(args);
89
- return explicitName
97
+ const resolved = explicitName
90
98
  || env.AGENT_NAME
91
99
  || fallbackName
92
100
  || getDefaultAgentName();
101
+ return assertSafeIdentitySegment(resolved, 'Agent name');
93
102
  }
94
103
 
95
104
  export function resolveRuntimeIdentity(fileConfig = {}, env = process.env) {
@@ -98,6 +107,17 @@ export function resolveRuntimeIdentity(fileConfig = {}, env = process.env) {
98
107
  return { agentName, instanceId };
99
108
  }
100
109
 
110
+ /** Resolve the default project working directory for an Agent display name. */
111
+ export function getDefaultWorkDir(agentName = DEFAULT_INSTANCE_ID) {
112
+ const normalizedName = getDefaultAgentName(String(agentName || '').trim() || DEFAULT_INSTANCE_ID);
113
+ return join(homedir(), '.yeaft', 'instances', normalizedName);
114
+ }
115
+
116
+ /** Resolve explicit workDir configuration before falling back to the Agent root. */
117
+ export function resolveAgentWorkDir(fileConfig = {}, env = process.env, agentName = DEFAULT_INSTANCE_ID) {
118
+ return env.WORK_DIR || fileConfig.workDir || getDefaultWorkDir(agentName);
119
+ }
120
+
101
121
  export function shouldLoadLegacyLocalConfig(env = process.env) {
102
122
  return !String(env.YEAFT_AGENT_INSTANCE || '').trim();
103
123
  }
package/service/index.js CHANGED
@@ -40,6 +40,8 @@ export {
40
40
  getPm2AppName,
41
41
  getLaunchdLabel,
42
42
  getDefaultYeaftDir,
43
+ getDefaultWorkDir,
44
+ resolveAgentWorkDir,
43
45
  } from './config.js';
44
46
  // Re-export the launchd plist-path resolver so consumers (e.g. the upgrade
45
47
  // flow) reach it via the service barrel instead of deep-importing macos.js.
package/service.js CHANGED
@@ -33,6 +33,8 @@ export {
33
33
  getLaunchdLabel,
34
34
  getLaunchdPlistPath,
35
35
  getDefaultYeaftDir,
36
+ getDefaultWorkDir,
37
+ resolveAgentWorkDir,
36
38
  install,
37
39
  uninstall,
38
40
  start,