@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 +14 -2
- package/local-runtime/server/handlers/client-browser.js +6 -2
- package/local-runtime/version.json +1 -1
- package/package.json +1 -1
- package/service/config.js +23 -3
- package/service/index.js +2 -0
- package/service.js +2 -0
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:
|
|
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:
|
|
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.
|
|
1
|
+
{"version":"1.0.436"}
|
package/package.json
CHANGED
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
|
-
|
|
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.
|