@cicctencent/agent-server 0.2.97 → 1.0.2
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/dist/cjs/automation/node-task-runtime.d.ts.map +1 -1
- package/dist/cjs/automation/node-task-runtime.js +196 -8
- package/dist/cjs/automation/node-task-runtime.js.map +1 -1
- package/dist/cjs/automation/node-task-validator.d.ts +10 -0
- package/dist/cjs/automation/node-task-validator.d.ts.map +1 -1
- package/dist/cjs/automation/node-task-validator.js +10 -0
- package/dist/cjs/automation/node-task-validator.js.map +1 -1
- package/dist/cjs/automation/python-prelude.d.ts +1 -1
- package/dist/cjs/automation/python-prelude.d.ts.map +1 -1
- package/dist/cjs/automation/python-prelude.js +196 -1
- package/dist/cjs/automation/python-prelude.js.map +1 -1
- package/dist/cjs/automation/python-task-runtime.d.ts.map +1 -1
- package/dist/cjs/automation/python-task-runtime.js +56 -4
- package/dist/cjs/automation/python-task-runtime.js.map +1 -1
- package/dist/cjs/sandbox/sandbox-prelude.d.ts +1 -1
- package/dist/cjs/sandbox/sandbox-prelude.d.ts.map +1 -1
- package/dist/cjs/sandbox/sandbox-prelude.js +55 -0
- package/dist/cjs/sandbox/sandbox-prelude.js.map +1 -1
- package/dist/esm/automation/node-task-runtime.d.ts.map +1 -1
- package/dist/esm/automation/node-task-runtime.js +196 -8
- package/dist/esm/automation/node-task-runtime.js.map +1 -1
- package/dist/esm/automation/node-task-validator.d.ts +10 -0
- package/dist/esm/automation/node-task-validator.d.ts.map +1 -1
- package/dist/esm/automation/node-task-validator.js +10 -0
- package/dist/esm/automation/node-task-validator.js.map +1 -1
- package/dist/esm/automation/python-prelude.d.ts +1 -1
- package/dist/esm/automation/python-prelude.d.ts.map +1 -1
- package/dist/esm/automation/python-prelude.js +196 -1
- package/dist/esm/automation/python-prelude.js.map +1 -1
- package/dist/esm/automation/python-task-runtime.d.ts.map +1 -1
- package/dist/esm/automation/python-task-runtime.js +56 -4
- package/dist/esm/automation/python-task-runtime.js.map +1 -1
- package/dist/esm/sandbox/sandbox-prelude.d.ts +1 -1
- package/dist/esm/sandbox/sandbox-prelude.d.ts.map +1 -1
- package/dist/esm/sandbox/sandbox-prelude.js +55 -0
- package/dist/esm/sandbox/sandbox-prelude.js.map +1 -1
- package/package.json +2 -2
|
@@ -28,12 +28,20 @@ import datetime as _dt
|
|
|
28
28
|
import urllib.request
|
|
29
29
|
import urllib.error
|
|
30
30
|
import urllib.parse
|
|
31
|
+
import threading
|
|
32
|
+
import hashlib
|
|
33
|
+
import uuid as _uuid
|
|
34
|
+
import random as _random
|
|
31
35
|
from typing import Any, Dict, List, Optional
|
|
32
36
|
|
|
33
37
|
# Agent 调用端点(由运行时注入)
|
|
34
38
|
_AGENT_ENDPOINT = "__AGENT_ENDPOINT__"
|
|
35
39
|
_AGENT_CONFIGURED = bool(_AGENT_ENDPOINT)
|
|
36
40
|
|
|
41
|
+
# 内存缓存(带 TTL),用于 sb.cache
|
|
42
|
+
_CACHE_STORE: Dict[str, Any] = {}
|
|
43
|
+
_CACHE_LOCK = threading.Lock()
|
|
44
|
+
|
|
37
45
|
|
|
38
46
|
class _Logger:
|
|
39
47
|
def __init__(self, sink):
|
|
@@ -235,14 +243,85 @@ def parse_date(text, fmt=None):
|
|
|
235
243
|
return _dt.datetime.fromisoformat(text)
|
|
236
244
|
|
|
237
245
|
|
|
238
|
-
def
|
|
246
|
+
def days_ago(n):
|
|
239
247
|
return _dt.datetime.now() - _dt.timedelta(days=n)
|
|
240
248
|
|
|
241
249
|
|
|
250
|
+
# 兼容旧名(文档与示例统一使用 sb.days_ago)
|
|
251
|
+
days_go = days_ago
|
|
252
|
+
|
|
253
|
+
|
|
242
254
|
def days_later(n):
|
|
243
255
|
return _dt.datetime.now() + _dt.timedelta(days=n)
|
|
244
256
|
|
|
245
257
|
|
|
258
|
+
# ===== 工具函数(Util) =====
|
|
259
|
+
|
|
260
|
+
def sleep(seconds):
|
|
261
|
+
"""阻塞当前协程/线程指定秒数。"""
|
|
262
|
+
time.sleep(seconds)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def uuid() -> str:
|
|
266
|
+
"""生成 UUID4 字符串。"""
|
|
267
|
+
return str(_uuid.uuid4())
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def hash(value, algo="sha256") -> str:
|
|
271
|
+
"""计算字符串/对象的哈希(默认 sha256)。"""
|
|
272
|
+
h = hashlib.new(algo)
|
|
273
|
+
h.update(str(value).encode("utf-8"))
|
|
274
|
+
return h.hexdigest()
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def random_int(min_value=0, max_value=100) -> int:
|
|
278
|
+
"""返回 [min_value, max_value] 区间内的随机整数。"""
|
|
279
|
+
return _random.randint(min_value, max_value)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def random_choice(seq):
|
|
283
|
+
"""从序列中随机取一个元素。"""
|
|
284
|
+
return _random.choice(seq)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def random_float(min_value=0.0, max_value=1.0) -> float:
|
|
288
|
+
"""返回 [min_value, max_value] 区间内的随机浮点数。"""
|
|
289
|
+
return _random.uniform(min_value, max_value)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def cache(key: str, ttl: Optional[float] = None):
|
|
293
|
+
"""带 TTL 的内存缓存访问器。
|
|
294
|
+
|
|
295
|
+
用法:
|
|
296
|
+
hits = sb.cache("api:hot", ttl=60).get(lambda: sb.get("/hot").get("data"))
|
|
297
|
+
sb.cache("api:hot").clear() # 清除该 key
|
|
298
|
+
|
|
299
|
+
ttl 为 None 表示永不过期(进程内)。
|
|
300
|
+
返回对象含 get(factory) / clear() 两个方法。
|
|
301
|
+
"""
|
|
302
|
+
class _CacheEntry:
|
|
303
|
+
__slots__ = ("value", "expire_at")
|
|
304
|
+
def __init__(self, value, expire_at):
|
|
305
|
+
self.value = value
|
|
306
|
+
self.expire_at = expire_at
|
|
307
|
+
|
|
308
|
+
def _get(factory):
|
|
309
|
+
now_ts = time.time()
|
|
310
|
+
with _CACHE_LOCK:
|
|
311
|
+
entry = _CACHE_STORE.get(key)
|
|
312
|
+
if entry is not None and (entry.expire_at is None or entry.expire_at > now_ts):
|
|
313
|
+
return entry.value
|
|
314
|
+
value = factory() if callable(factory) else factory
|
|
315
|
+
_CACHE_STORE[key] = _CacheEntry(value, now_ts + ttl if ttl else None)
|
|
316
|
+
return value
|
|
317
|
+
|
|
318
|
+
def _clear():
|
|
319
|
+
with _CACHE_LOCK:
|
|
320
|
+
_CACHE_STORE.pop(key, None)
|
|
321
|
+
|
|
322
|
+
return type("CacheHandle", (), {"get": _get, "clear": _clear})()
|
|
323
|
+
|
|
324
|
+
|
|
246
325
|
# ===== Agent =====
|
|
247
326
|
|
|
248
327
|
class _Agent:
|
|
@@ -255,11 +334,18 @@ class _Agent:
|
|
|
255
334
|
- 流式逐 token 返回,避免非流式 HTTP 长等待超时;
|
|
256
335
|
- 服务端每 3s 发送心跳,保持连接活跃;
|
|
257
336
|
- timeout 为单次读取超时(默认 600s),流式心跳保证不会因空闲而超时。
|
|
337
|
+
|
|
338
|
+
options:
|
|
339
|
+
- timeout : 单次读取超时(秒)
|
|
340
|
+
- contextId : 会话上下文 id(用于多轮记忆)
|
|
341
|
+
- profile : Agent profile(名称或 id)
|
|
342
|
+
- json : True 时把最终文本按 JSON 解析并返回对象(自动去除 \`\`\` 代码围栏)
|
|
258
343
|
"""
|
|
259
344
|
if not _AGENT_CONFIGURED:
|
|
260
345
|
raise RuntimeError("Agent endpoint not configured")
|
|
261
346
|
options = options or {}
|
|
262
347
|
timeout = options.get("timeout", 600)
|
|
348
|
+
json_mode = options.get("json", False)
|
|
263
349
|
payload = {
|
|
264
350
|
"jsonrpc": "2.0",
|
|
265
351
|
"id": options.get("id", 1),
|
|
@@ -323,8 +409,117 @@ class _Agent:
|
|
|
323
409
|
pass
|
|
324
410
|
if task_failed:
|
|
325
411
|
raise RuntimeError("Agent task failed: %s" % (task_error or "unknown"))
|
|
412
|
+
if json_mode:
|
|
413
|
+
return _parse_json_text(final_text)
|
|
326
414
|
return final_text
|
|
327
415
|
|
|
416
|
+
def stream(self, prompt, options=None):
|
|
417
|
+
"""流式调用 Agent,增量 yield 文本片段(delta)。
|
|
418
|
+
|
|
419
|
+
A2A 的 message 事件通常携带「到目前为止的完整文本」,故与前一次文本做前缀
|
|
420
|
+
比较,只输出新增部分(delta),避免重复。
|
|
421
|
+
|
|
422
|
+
options 同 ask(timeout / contextId / profile / json)。
|
|
423
|
+
json=True 时,流式结束后额外 yield 一次解析后的对象(最后一次 yield 为 dict)。
|
|
424
|
+
"""
|
|
425
|
+
if not _AGENT_CONFIGURED:
|
|
426
|
+
raise RuntimeError("Agent endpoint not configured")
|
|
427
|
+
options = options or {}
|
|
428
|
+
timeout = options.get("timeout", 600)
|
|
429
|
+
json_mode = options.get("json", False)
|
|
430
|
+
payload = {
|
|
431
|
+
"jsonrpc": "2.0",
|
|
432
|
+
"id": options.get("id", 1),
|
|
433
|
+
"method": "tasks/sendSubscribe",
|
|
434
|
+
"params": {
|
|
435
|
+
"message": {
|
|
436
|
+
"role": "user",
|
|
437
|
+
"parts": [{"kind": "text", "text": str(prompt)}],
|
|
438
|
+
},
|
|
439
|
+
"contextId": options.get("contextId"),
|
|
440
|
+
"profile": options.get("profile"),
|
|
441
|
+
},
|
|
442
|
+
}
|
|
443
|
+
data = json.dumps(payload).encode("utf-8")
|
|
444
|
+
req = urllib.request.Request(
|
|
445
|
+
_AGENT_ENDPOINT,
|
|
446
|
+
data=data,
|
|
447
|
+
headers={
|
|
448
|
+
"Content-Type": "application/json",
|
|
449
|
+
"Accept": "text/event-stream",
|
|
450
|
+
|
|
451
|
+
"User-Agent": "workai-sandbox/1.0",
|
|
452
|
+
},
|
|
453
|
+
method="POST",
|
|
454
|
+
)
|
|
455
|
+
last = ""
|
|
456
|
+
buf = b""
|
|
457
|
+
try:
|
|
458
|
+
resp = urllib.request.urlopen(req, timeout=timeout)
|
|
459
|
+
except urllib.error.HTTPError as e:
|
|
460
|
+
raise RuntimeError("Agent call failed (HTTP %s)" % e.code)
|
|
461
|
+
try:
|
|
462
|
+
for raw in resp:
|
|
463
|
+
buf += raw
|
|
464
|
+
while b"\n\n" in buf:
|
|
465
|
+
block, buf = buf.split(b"\n\n", 1)
|
|
466
|
+
text = block.decode("utf-8", errors="replace")
|
|
467
|
+
for line in text.splitlines():
|
|
468
|
+
if not line.startswith("data:"):
|
|
469
|
+
continue
|
|
470
|
+
payload_str = line[5:].strip()
|
|
471
|
+
if not payload_str:
|
|
472
|
+
continue
|
|
473
|
+
try:
|
|
474
|
+
msg = json.loads(payload_str)
|
|
475
|
+
except Exception:
|
|
476
|
+
continue
|
|
477
|
+
result = msg.get("result") or {}
|
|
478
|
+
etype = result.get("type")
|
|
479
|
+
edata = result.get("data")
|
|
480
|
+
if etype == "error":
|
|
481
|
+
err_msg = edata.get("message") if isinstance(edata, dict) else str(edata)
|
|
482
|
+
raise RuntimeError("Agent error: %s" % err_msg)
|
|
483
|
+
t = ""
|
|
484
|
+
if etype == "message" and isinstance(edata, dict):
|
|
485
|
+
for p in (edata.get("parts") or []):
|
|
486
|
+
if (p.get("kind") == "text" or p.get("type") == "text") and p.get("text"):
|
|
487
|
+
t = p["text"]
|
|
488
|
+
elif etype == "task" and isinstance(edata, dict) and edata.get("state") == "failed":
|
|
489
|
+
raise RuntimeError("Agent task failed: %s" % (edata.get("error") or "unknown"))
|
|
490
|
+
if not t:
|
|
491
|
+
continue
|
|
492
|
+
# 前缀差量:只输出新增内容
|
|
493
|
+
if t.startswith(last):
|
|
494
|
+
delta = t[len(last):]
|
|
495
|
+
if delta:
|
|
496
|
+
yield delta
|
|
497
|
+
else:
|
|
498
|
+
yield t
|
|
499
|
+
last = t
|
|
500
|
+
finally:
|
|
501
|
+
try:
|
|
502
|
+
resp.close()
|
|
503
|
+
except Exception:
|
|
504
|
+
pass
|
|
505
|
+
if json_mode and last:
|
|
506
|
+
yield _parse_json_text(last)
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def _parse_json_text(text):
|
|
510
|
+
"""把 Agent 返回文本按 JSON 解析(自动去除 \`\`\`json 代码围栏)。"""
|
|
511
|
+
s = (text or "").strip()
|
|
512
|
+
if s.startswith("\`\`\`"):
|
|
513
|
+
# 去除首行围栏(\`\`\`json / \`\`\`)
|
|
514
|
+
s = s.split("\n", 1)[1] if "\n" in s else s[3:]
|
|
515
|
+
if s.endswith("\`\`\`"):
|
|
516
|
+
s = s[:-3]
|
|
517
|
+
s = s.strip()
|
|
518
|
+
try:
|
|
519
|
+
return json.loads(s)
|
|
520
|
+
except Exception:
|
|
521
|
+
raise RuntimeError("Agent 返回内容不是合法 JSON: %s" % s[:200])
|
|
522
|
+
|
|
328
523
|
|
|
329
524
|
agent = _Agent()
|
|
330
525
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-prelude.js","sourceRoot":"","sources":["../../../src/automation/python-prelude.ts"],"names":[],"mappings":";AAAA,+DAA+D;AAC/D,gDAAgD;AAChD,+DAA+D;AAC/D,kDAAkD;AAClD,kEAAkE;AAClE,6CAA6C;AAC7C,+DAA+D;;;AAE/D;;;GAGG;AACU,QAAA,qBAAqB,GAAG
|
|
1
|
+
{"version":3,"file":"python-prelude.js","sourceRoot":"","sources":["../../../src/automation/python-prelude.ts"],"names":[],"mappings":";AAAA,+DAA+D;AAC/D,gDAAgD;AAChD,+DAA+D;AAC/D,kDAAkD;AAClD,kEAAkE;AAClE,6CAA6C;AAC7C,+DAA+D;;;AAE/D;;;GAGG;AACU,QAAA,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8fpC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-task-runtime.d.ts","sourceRoot":"","sources":["../../../src/automation/python-task-runtime.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AAKjC,MAAM,WAAW,8BAA8B;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAYD,qBAAa,6BAA6B;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,8BAAmC;IAIlD,OAAO,CACX,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,6BAA6B,CAAC;IAqCzC;;;OAGG;IACG,aAAa,CACjB,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,EACjC,SAAS,GAAE;QACT,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;QAChD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACnC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,6BAA6B,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAChC,GACL,OAAO,CAAC,6BAA6B,CAAC;IAoDzC,+CAA+C;IAC/C,OAAO,CAAC,cAAc;IA8BtB,2CAA2C;IAC3C,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,oBAAoB;
|
|
1
|
+
{"version":3,"file":"python-task-runtime.d.ts","sourceRoot":"","sources":["../../../src/automation/python-task-runtime.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AAKjC,MAAM,WAAW,8BAA8B;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAYD,qBAAa,6BAA6B;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,8BAAmC;IAIlD,OAAO,CACX,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,6BAA6B,CAAC;IAqCzC;;;OAGG;IACG,aAAa,CACjB,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,EACjC,SAAS,GAAE;QACT,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;QAChD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACnC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,6BAA6B,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAChC,GACL,OAAO,CAAC,6BAA6B,CAAC;IAoDzC,+CAA+C;IAC/C,OAAO,CAAC,cAAc;IA8BtB,2CAA2C;IAC3C,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,oBAAoB;IA8I5B,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,iBAAiB;CAU1B;AAID,wBAAgB,gCAAgC,IAAI,6BAA6B,CAGhF"}
|
|
@@ -225,24 +225,64 @@ for __file, __content in (__task.get("sourceFiles") or {}).items():
|
|
|
225
225
|
with open(__target, "w", encoding="utf-8") as __f:
|
|
226
226
|
__f.write(__content)
|
|
227
227
|
|
|
228
|
+
# 产物大小上限(单文件默认 5MB,避免超大产物撑爆存储/响应)
|
|
229
|
+
ARTIFACT_MAX_BYTES = 5 * 1024 * 1024
|
|
230
|
+
|
|
231
|
+
def __artifact_guard(content):
|
|
232
|
+
if isinstance(content, (bytes, bytearray)):
|
|
233
|
+
size = len(content)
|
|
234
|
+
else:
|
|
235
|
+
size = len(str(content).encode("utf-8"))
|
|
236
|
+
if size > ARTIFACT_MAX_BYTES:
|
|
237
|
+
raise RuntimeError("产物体积超限(最大 %d 字节): 实际 %d" % (ARTIFACT_MAX_BYTES, size))
|
|
238
|
+
return content
|
|
239
|
+
|
|
228
240
|
# 构造 context(与 Node 端结构对齐)
|
|
241
|
+
# secrets:仅暴露白名单环境变量(与 env 同源),供任务安全读取凭证,避免误用 os.environ 全量泄露。
|
|
229
242
|
__context = {
|
|
230
243
|
"taskId": __data["taskId"],
|
|
231
244
|
"runId": __data["runId"],
|
|
232
245
|
"inputs": __data["inputs"],
|
|
233
246
|
"env": __data["env"],
|
|
247
|
+
"secrets": __data["env"],
|
|
234
248
|
"workspace": __data["workspace"],
|
|
235
249
|
"logger": sb._Logger(__log),
|
|
236
250
|
"artifacts": type("A", (), {
|
|
237
|
-
"writeText": staticmethod(lambda f, c: sb.write_text(f,
|
|
238
|
-
"write_text": staticmethod(lambda f, c: sb.write_text(f,
|
|
251
|
+
"writeText": staticmethod(lambda f, c: sb.write_text(f, __artifact_guard(c))),
|
|
252
|
+
"write_text": staticmethod(lambda f, c: sb.write_text(f, __artifact_guard(c))),
|
|
239
253
|
"writeJson": staticmethod(lambda f, d: sb.write_json(f, d)),
|
|
240
254
|
"write_json": staticmethod(lambda f, d: sb.write_json(f, d)),
|
|
255
|
+
"readText": staticmethod(lambda f: sb.read_text(f)),
|
|
256
|
+
"read_text": staticmethod(lambda f: sb.read_text(f)),
|
|
257
|
+
"readJson": staticmethod(lambda f: sb.read_json(f)),
|
|
258
|
+
"read_json": staticmethod(lambda f: sb.read_json(f)),
|
|
241
259
|
})(),
|
|
242
260
|
"agent": sb.agent,
|
|
243
261
|
}
|
|
244
262
|
|
|
263
|
+
def __validate_inputs(schema, inputs):
|
|
264
|
+
"""运行前校验 inputsSchema(JSON Schema 子集:properties / required / type)。"""
|
|
265
|
+
if not schema or not isinstance(schema, dict):
|
|
266
|
+
return
|
|
267
|
+
props = schema.get("properties") or {}
|
|
268
|
+
required = schema.get("required") or []
|
|
269
|
+
if not isinstance(inputs, dict):
|
|
270
|
+
raise RuntimeError("inputs 必须是对象,但收到 %s" % type(inputs).__name__)
|
|
271
|
+
for key in required:
|
|
272
|
+
if key not in inputs:
|
|
273
|
+
raise RuntimeError("缺少必填输入项: %s" % key)
|
|
274
|
+
__type_map = {"string": str, "number": (int, float), "integer": int,
|
|
275
|
+
"boolean": bool, "array": list, "object": dict}
|
|
276
|
+
for key, val in inputs.items():
|
|
277
|
+
if key in props and isinstance(props[key], dict):
|
|
278
|
+
expected = props[key].get("type")
|
|
279
|
+
if expected and expected in __type_map and not isinstance(val, __type_map[expected]):
|
|
280
|
+
raise RuntimeError("输入项 %s 类型错误:期望 %s,实际 %s" % (key, expected, type(val).__name__))
|
|
281
|
+
|
|
245
282
|
def __run():
|
|
283
|
+
# 运行前校验输入 Schema(顶层 inputsSchema 或 metadata.inputsSchema)
|
|
284
|
+
__schema = __task.get("inputsSchema") or (__task.get("metadata") or {}).get("inputsSchema")
|
|
285
|
+
__validate_inputs(__schema, __data["inputs"])
|
|
246
286
|
__entry = __task["entry"]
|
|
247
287
|
__mod_name = os.path.splitext(__entry)[0].replace(os.sep, ".")
|
|
248
288
|
import importlib
|
|
@@ -251,13 +291,25 @@ def __run():
|
|
|
251
291
|
raise RuntimeError("Python automation entry must define run(context)")
|
|
252
292
|
return __mod.run(__context)
|
|
253
293
|
|
|
294
|
+
__start = time.time()
|
|
254
295
|
try:
|
|
255
296
|
__result = __run()
|
|
297
|
+
__duration_ms = int((time.time() - __start) * 1000)
|
|
298
|
+
__log("info", "task finished", {"durationMs": __duration_ms})
|
|
256
299
|
print("__NODE_AUTOMATION_RESULT__" + json.dumps({"result": __result}, ensure_ascii=False, default=str))
|
|
257
300
|
except Exception as e:
|
|
258
|
-
|
|
301
|
+
__duration_ms = int((time.time() - __start) * 1000)
|
|
302
|
+
__log("error", str(e), {"durationMs": __duration_ms})
|
|
259
303
|
traceback.print_exc()
|
|
260
|
-
|
|
304
|
+
# 结构化错误:type / code / retryable 供 UI 友好展示与重试策略判断
|
|
305
|
+
__err = {
|
|
306
|
+
"message": str(e),
|
|
307
|
+
"type": type(e).__name__,
|
|
308
|
+
"code": "TASK_EXECUTION_FAILED",
|
|
309
|
+
"retryable": isinstance(e, (RuntimeError, TimeoutError, ConnectionError, OSError)),
|
|
310
|
+
"durationMs": __duration_ms,
|
|
311
|
+
}
|
|
312
|
+
print("__NODE_AUTOMATION_ERROR__" + json.dumps(__err, ensure_ascii=False, default=str))
|
|
261
313
|
sys.exit(1)
|
|
262
314
|
`;
|
|
263
315
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-task-runtime.js","sourceRoot":"","sources":["../../../src/automation/python-task-runtime.ts"],"names":[],"mappings":";AAAA,+DAA+D;AAC/D,+CAA+C;AAC/C,+DAA+D;AAC/D,4DAA4D;AAC5D,6CAA6C;AAC7C,+DAA+D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"python-task-runtime.js","sourceRoot":"","sources":["../../../src/automation/python-task-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,5 +50,5 @@ export declare function clearSandboxPreludeExtensions(): void;
|
|
|
50
50
|
* 在沙箱初始化时写入 _scripts/_prelude.cjs
|
|
51
51
|
* 通过 runScript Node.js preamble 自动 require 为 global.sb
|
|
52
52
|
*/
|
|
53
|
-
export declare const SANDBOX_PRELUDE_SOURCE = "'use strict';\n// ============================================================\n// Sandbox Prelude - Auto-loaded as global `sb` in Node.js scripts\n// Common utilities so you only write business logic.\n// Loads extensions from _prelude_ext/ at require time.\n// ============================================================\n\nconst fs = require('fs');\nconst path = require('path');\nconst https = require('https');\nconst http = require('http');\nconst { URL } = require('url');\n\n// ===== Helpers =====\n\n// Safe JSON stringify (handles circular references)\nfunction _safeStringify(v) {\n try { return JSON.stringify(v); } catch (e) { return String(v); }\n}\n\n// ===== HTTP =====\n\n/**\n * fetch - HTTP request with timeout, JSON parsing and redirect following\n * @param {string} url - Request URL\n * @param {object} options - { method, headers, body, json, params, timeout, maxRedirects }\n * @returns {Promise<{status, headers, data, text}>}\n */\nasync function fetch(url, options = {}, _depth = 0) {\n const {\n method = 'GET',\n headers = {},\n body,\n json,\n timeout = 30000,\n params,\n maxRedirects = 3,\n } = options;\n let targetUrl = url;\n if (params) {\n const u = new URL(targetUrl);\n for (const [k, v] of Object.entries(params)) u.searchParams.set(k, String(v));\n targetUrl = u.toString();\n }\n const u = new URL(targetUrl);\n const lib = u.protocol === 'https:' ? https : http;\n const reqHeaders = { 'User-Agent': 'workai-sandbox/1.0', ...headers };\n let reqBody = body;\n if (json !== undefined) {\n reqBody = JSON.stringify(json);\n reqHeaders['Content-Type'] = reqHeaders['Content-Type'] || 'application/json';\n }\n return new Promise((resolve, reject) => {\n const req = lib.request(u, { method, headers: reqHeaders, timeout }, (res) => {\n const status = res.statusCode;\n // Follow redirects (301/302/303/307/308)\n if (\n (status === 301 || status === 302 || status === 303 || status === 307 || status === 308) &&\n res.headers.location &&\n _depth < maxRedirects\n ) {\n res.resume(); // discard response body\n const nextUrl = new URL(res.headers.location, targetUrl).toString();\n const nextMethod = status === 303 ? 'GET' : method;\n const nextBody = status === 303 ? undefined : body;\n const nextJson = status === 303 ? undefined : json;\n resolve(fetch(nextUrl, { ...options, method: nextMethod, body: nextBody, json: nextJson }, _depth + 1));\n return;\n }\n const chunks = [];\n res.on('data', (c) => chunks.push(c));\n res.on('end', () => {\n const buf = Buffer.concat(chunks);\n const text = buf.toString('utf-8');\n let data = text;\n const ct = (res.headers['content-type'] || '').toLowerCase();\n if (ct.includes('application/json') || ct.includes('+json')) {\n try { data = JSON.parse(text); } catch (e) { /* keep text */ }\n }\n resolve({ status: status, headers: res.headers, data, text });\n });\n });\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(new Error('Request timeout after ' + timeout + 'ms')); });\n if (reqBody) req.write(reqBody);\n req.end();\n });\n}\n\n/** GET request shorthand */\nasync function get(url, options = {}) {\n return fetch(url, { ...options, method: 'GET' });\n}\n\n/** POST request shorthand (auto-JSON for object bodies) */\nasync function post(url, body, options = {}) {\n const isJson = typeof body === 'object' && body !== null && !Buffer.isBuffer(body);\n return fetch(url, {\n ...options,\n method: 'POST',\n json: isJson ? body : undefined,\n body: isJson ? undefined : body,\n });\n}\n\n/** PUT request shorthand (auto-JSON for object bodies) */\nasync function put(url, body, options = {}) {\n const isJson = typeof body === 'object' && body !== null && !Buffer.isBuffer(body);\n return fetch(url, {\n ...options,\n method: 'PUT',\n json: isJson ? body : undefined,\n body: isJson ? undefined : body,\n });\n}\n\n/** HEAD request shorthand */\nasync function head(url, options = {}) {\n return fetch(url, { ...options, method: 'HEAD' });\n}\n\n/** DELETE request shorthand */\nasync function del(url, options = {}) {\n return fetch(url, { ...options, method: 'DELETE' });\n}\n\n// ===== File I/O =====\n\nfunction readJson(file) {\n const content = fs.readFileSync(file, 'utf-8');\n return JSON.parse(content);\n}\n\nfunction writeJson(file, data, indent = 2) {\n const dir = path.dirname(file);\n if (dir && dir !== '.') try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}\n fs.writeFileSync(file, JSON.stringify(data, null, indent), 'utf-8');\n}\n\nfunction readText(file, encoding = 'utf-8') {\n return fs.readFileSync(file, encoding);\n}\n\nfunction writeText(file, content) {\n const dir = path.dirname(file);\n if (dir && dir !== '.') try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}\n fs.writeFileSync(file, content, 'utf-8');\n}\n\nfunction appendText(file, content) {\n const dir = path.dirname(file);\n if (dir && dir !== '.') try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}\n fs.appendFileSync(file, content, 'utf-8');\n}\n\nfunction exists(p) {\n try { return fs.existsSync(p); } catch (e) { return false; }\n}\n\nfunction listDir(dir) {\n return fs.readdirSync(dir).map(function (name) {\n let stat;\n try { stat = fs.statSync(path.join(dir, name)); } catch (e) { return name; }\n return stat.isDirectory() ? name + '/' : name;\n });\n}\n\n/**\n * readCsv - parse CSV file into array of objects\n * @param {string} file - CSV file path\n * @param {object} opts - { delimiter, headers }\n * headers: \u81EA\u5B9A\u4E49\u8868\u5934\u6570\u7EC4\uFF1B\u82E5\u63D0\u4F9B\u5219\u9996\u884C\u88AB\u89C6\u4E3A\u6570\u636E\u884C\uFF0C\u5426\u5219\u9996\u884C\u4F5C\u4E3A\u8868\u5934\n * @returns {Array<object>}\n */\nfunction readCsv(file, opts = {}) {\n const delimiter = opts.delimiter || ',';\n const content = fs.readFileSync(file, 'utf-8');\n const lines = content.split(/\\r?\\n/).filter(function (l) { return l.trim(); });\n if (lines.length === 0) return [];\n const parseLine = function (line) {\n const result = [];\n let cur = '';\n let inQuote = false;\n for (let i = 0; i < line.length; i++) {\n const c = line[i];\n if (c === '\"') {\n if (inQuote && line[i + 1] === '\"') { cur += '\"'; i++; }\n else inQuote = !inQuote;\n } else if (c === delimiter && !inQuote) {\n result.push(cur); cur = '';\n } else {\n cur += c;\n }\n }\n result.push(cur);\n return result.map(function (s) { return s.trim(); });\n };\n const headers = opts.headers || parseLine(lines[0]);\n const startIdx = opts.headers ? 0 : 1;\n const rows = [];\n for (let i = startIdx; i < lines.length; i++) {\n const values = parseLine(lines[i]);\n const row = {};\n headers.forEach(function (h, j) { row[h] = values[j] || ''; });\n rows.push(row);\n }\n return rows;\n}\n\n/**\n * writeCsv - write array of objects to CSV file\n * @param {string} file - Output CSV file path\n * @param {Array<object>} rows - Data rows\n * @param {object} opts - { headers, delimiter }\n */\nfunction writeCsv(file, rows, opts = {}) {\n if (!rows || rows.length === 0) {\n writeText(file, '');\n return;\n }\n const delimiter = opts.delimiter || ',';\n const headers = opts.headers || Object.keys(rows[0]);\n const escapeCell = function (val) {\n const s = String(val == null ? '' : val);\n if (s.includes(delimiter) || s.includes('\"') || s.includes('\\n')) {\n return '\"' + s.replace(/\"/g, '\"\"') + '\"';\n }\n return s;\n };\n const lines = [headers.map(escapeCell).join(delimiter)];\n for (const row of rows) {\n lines.push(headers.map(function (h) { return escapeCell(row[h]); }).join(delimiter));\n }\n writeText(file, lines.join('\\n'));\n}\n\n// ===== Data Utilities =====\n\n/** Calculate statistics: sum, avg, min, max, count, std */\nfunction stats(arr) {\n const nums = arr.map(Number).filter(function (n) { return !isNaN(n); });\n if (nums.length === 0) return { count: 0, sum: 0, avg: 0, min: 0, max: 0, std: 0 };\n const sumVal = nums.reduce(function (a, b) { return a + b; }, 0);\n const avgVal = sumVal / nums.length;\n const min = Math.min.apply(null, nums);\n const max = Math.max.apply(null, nums);\n const variance = nums.reduce(function (acc, n) { return acc + Math.pow(n - avgVal, 2); }, 0) / nums.length;\n return { count: nums.length, sum: sumVal, avg: avgVal, min: min, max: max, std: Math.sqrt(variance) };\n}\n\nfunction sum(arr) {\n return arr.reduce(function (a, b) { return a + (Number(b) || 0); }, 0);\n}\n\nfunction avg(arr) {\n if (arr.length === 0) return 0;\n return sum(arr) / arr.length;\n}\n\nfunction groupBy(arr, keyFn) {\n const result = {};\n for (const item of arr) {\n const key = typeof keyFn === 'function' ? keyFn(item) : item[keyFn];\n if (!result[key]) result[key] = [];\n result[key].push(item);\n }\n return result;\n}\n\nfunction sortBy(arr, keyFn, desc) {\n const fn = typeof keyFn === 'function' ? keyFn : function (x) { return x[keyFn]; };\n return arr.slice().sort(function (a, b) {\n const va = fn(a);\n const vb = fn(b);\n if (va < vb) return desc ? 1 : -1;\n if (va > vb) return desc ? -1 : 1;\n return 0;\n });\n}\n\nfunction unique(arr, keyFn) {\n if (!keyFn) {\n return arr.filter(function (v, i, self) { return self.indexOf(v) === i; });\n }\n const fn = typeof keyFn === 'function' ? keyFn : function (x) { return x[keyFn]; };\n const seen = new Set();\n return arr.filter(function (x) {\n const k = fn(x);\n if (seen.has(k)) return false;\n seen.add(k);\n return true;\n });\n}\n\nfunction chunk(arr, size) {\n size = Math.max(1, size || 1);\n const result = [];\n for (let i = 0; i < arr.length; i += size) {\n result.push(arr.slice(i, i + size));\n }\n return result;\n}\n\nfunction range(start, end, step) {\n step = step || 1;\n if (end === undefined) { end = start; start = 0; }\n const result = [];\n if (step > 0) {\n for (let i = start; i < end; i += step) result.push(i);\n } else {\n for (let i = start; i > end; i += step) result.push(i);\n }\n return result;\n}\n\nfunction pick(obj, keys) {\n const result = {};\n for (const k of keys) {\n if (k in obj) result[k] = obj[k];\n }\n return result;\n}\n\nfunction omit(obj, keys) {\n const keySet = new Set(keys);\n const result = {};\n for (const k of Object.keys(obj)) {\n if (!keySet.has(k)) result[k] = obj[k];\n }\n return result;\n}\n\nfunction flatten(arr) {\n return arr.reduce(function (flat, sub) { return flat.concat(Array.isArray(sub) ? sub : [sub]); }, []);\n}\n\n// ===== Date Utilities =====\n\nfunction formatDate(date, format) {\n const d = date instanceof Date ? date : new Date(date);\n if (isNaN(d.getTime())) return 'Invalid Date';\n const pad = function (n) { return n < 10 ? '0' + n : '' + n; };\n const map = {\n YYYY: d.getFullYear(),\n MM: pad(d.getMonth() + 1),\n DD: pad(d.getDate()),\n HH: pad(d.getHours()),\n mm: pad(d.getMinutes()),\n ss: pad(d.getSeconds()),\n };\n let result = format || 'YYYY-MM-DD HH:mm:ss';\n for (const k in map) {\n result = result.replace(k, map[k]);\n }\n return result;\n}\n\nfunction parseDate(str) {\n if (typeof str === 'number') return new Date(str);\n const d = new Date(str);\n if (!isNaN(d.getTime())) return d;\n const m = String(str).match(/^(\\d{4})[-\\/](\\d{1,2})[-\\/](\\d{1,2})/);\n if (m) return new Date(parseInt(m[1], 10), parseInt(m[2], 10) - 1, parseInt(m[3], 10));\n return null;\n}\n\nfunction now() {\n return new Date().toISOString();\n}\n\nfunction daysAgo(n) {\n const d = new Date();\n d.setDate(d.getDate() - n);\n return d;\n}\n\nfunction daysLater(n) {\n const d = new Date();\n d.setDate(d.getDate() + n);\n return d;\n}\n\nfunction dateDiff(d1, d2, unit) {\n const date1 = d1 instanceof Date ? d1 : new Date(d1);\n const date2 = d2 instanceof Date ? d2 : new Date(d2);\n const diffMs = Math.abs(date2.getTime() - date1.getTime());\n unit = unit || 'days';\n switch (unit) {\n case 'seconds': return Math.floor(diffMs / 1000);\n case 'minutes': return Math.floor(diffMs / 60000);\n case 'hours': return Math.floor(diffMs / 3600000);\n case 'days': return Math.floor(diffMs / 86400000);\n default: return diffMs;\n }\n}\n\n// ===== String Utilities =====\n\n/**\n * template - Simple template interpolation\n * @param {string} str - Template string with {variable} or {a.b.c} placeholders\n * @param {object} data - Data object\n * @returns {string}\n */\nfunction template(str, data) {\n return str.replace(/\\{([^}]+)\\}/g, function (match, key) {\n const value = key.trim().split('.').reduce(function (obj, k) {\n return obj && obj[k] !== undefined ? obj[k] : undefined;\n }, data);\n return value !== undefined && value !== null ? String(value) : '';\n });\n}\n\nfunction slugify(str) {\n return String(str)\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\nfunction truncate(str, len, suffix) {\n if (String(str).length <= len) return String(str);\n return String(str).substring(0, len) + (suffix || '...');\n}\n\nfunction pad(str, len, char, right) {\n str = String(str);\n char = char || ' ';\n const diff = len - str.length;\n if (diff <= 0) return str;\n const padding = char.repeat(diff);\n return right ? str + padding : padding + str;\n}\n\n// ===== Table Generators =====\n\n/**\n * markdownTable - Generate markdown table from array of objects\n * @param {Array<object>} rows - Data rows\n * @param {Array<string>} headers - Optional custom headers (defaults to Object.keys of first row)\n * @returns {string} Markdown table string\n */\nfunction markdownTable(rows, headers) {\n if (!rows || rows.length === 0) return '';\n headers = headers || Object.keys(rows[0]);\n const lines = [];\n lines.push('| ' + headers.join(' | ') + ' |');\n lines.push('| ' + headers.map(function () { return '---'; }).join(' | ') + ' |');\n for (const row of rows) {\n lines.push('| ' + headers.map(function (h) {\n return String(row[h] == null ? '' : row[h]).replace(/\\|/g, '\\\\|');\n }).join(' | ') + ' |');\n }\n return lines.join('\\n');\n}\n\n/**\n * htmlTable - Generate HTML table from array of objects\n * @param {Array<object>} rows - Data rows\n * @param {object} opts - { headers, tableClass }\n * @returns {string} HTML table string\n */\nfunction htmlTable(rows, opts = {}) {\n if (!rows || rows.length === 0) return '<table><tbody></tbody></table>';\n const headers = opts.headers || Object.keys(rows[0]);\n const tableClass = opts.tableClass ? ' class=\"' + opts.tableClass + '\"' : '';\n const parts = ['<table' + tableClass + '>'];\n parts.push('<thead><tr>');\n for (const h of headers) {\n parts.push('<th>' + h + '</th>');\n }\n parts.push('</tr></thead><tbody>');\n for (const row of rows) {\n parts.push('<tr>');\n for (const h of headers) {\n parts.push('<td>' + String(row[h] == null ? '' : row[h]) + '</td>');\n }\n parts.push('</tr>');\n }\n parts.push('</tbody></table>');\n return parts.join('');\n}\n\n// ===== Logger =====\n\nconst log = {\n info: function (msg, meta) { console.log('[INFO] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n warn: function (msg, meta) { console.warn('[WARN] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n error: function (msg, meta) { console.error('[ERROR] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n debug: function (msg, meta) { console.log('[DEBUG] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n};\n\n// ===== Core exports =====\n\nconst _exports = {\n // HTTP\n fetch: fetch,\n get: get,\n post: post,\n put: put,\n head: head,\n del: del,\n // File I/O\n readJson: readJson,\n writeJson: writeJson,\n readText: readText,\n writeText: writeText,\n appendText: appendText,\n readCsv: readCsv,\n writeCsv: writeCsv,\n exists: exists,\n listDir: listDir,\n // Data\n stats: stats,\n sum: sum,\n avg: avg,\n groupBy: groupBy,\n sortBy: sortBy,\n unique: unique,\n chunk: chunk,\n range: range,\n pick: pick,\n omit: omit,\n flatten: flatten,\n // Date\n formatDate: formatDate,\n parseDate: parseDate,\n now: now,\n daysAgo: daysAgo,\n daysLater: daysLater,\n dateDiff: dateDiff,\n // String\n template: template,\n slugify: slugify,\n truncate: truncate,\n pad: pad,\n // Table\n markdownTable: markdownTable,\n htmlTable: htmlTable,\n // Logger\n log: log,\n // fs/path passthrough for convenience\n fs: fs,\n path: path,\n};\n\nmodule.exports = _exports;\n\n// ===== Load extensions from _prelude_ext/ =====\n// \u6269\u5C55\u6A21\u5757\u901A\u8FC7 module.exports \u5BFC\u51FA\u5BF9\u8C61\uFF0C\u52A0\u8F7D\u65F6\u5408\u5E76\u8FDB sb\uFF08\u540C\u540D\u8986\u76D6\u6838\u5FC3\uFF0C\u4FBF\u4E8E\u5B9A\u5236\uFF09\n(function loadPreludeExtensions() {\n try {\n const extDir = path.join(__dirname, '_prelude_ext');\n if (!fs.existsSync(extDir)) return;\n const extFiles = fs.readdirSync(extDir).filter(function (f) {\n return f.endsWith('.cjs') && f !== 'index.cjs';\n });\n for (const f of extFiles) {\n try {\n const mod = require(path.join(extDir, f));\n const ext = mod && mod.__esModule && mod.default ? mod.default : mod;\n if (ext && typeof ext === 'object') {\n for (const key of Object.keys(ext)) {\n _exports[key] = ext[key];\n }\n }\n } catch (e) {\n console.warn('[prelude] Failed to load extension \"' + f + '\": ' + (e && e.message));\n }\n }\n } catch (e) { /* ignore extension load errors */ }\n})();\n";
|
|
53
|
+
export declare const SANDBOX_PRELUDE_SOURCE = "'use strict';\n// ============================================================\n// Sandbox Prelude - Auto-loaded as global `sb` in Node.js scripts\n// Common utilities so you only write business logic.\n// Loads extensions from _prelude_ext/ at require time.\n// ============================================================\n\nconst fs = require('fs');\nconst path = require('path');\nconst https = require('https');\nconst http = require('http');\nconst { URL } = require('url');\n\n// ===== Helpers =====\n\n// Safe JSON stringify (handles circular references)\nfunction _safeStringify(v) {\n try { return JSON.stringify(v); } catch (e) { return String(v); }\n}\n\n// ===== HTTP =====\n\n/**\n * fetch - HTTP request with timeout, JSON parsing and redirect following\n * @param {string} url - Request URL\n * @param {object} options - { method, headers, body, json, params, timeout, maxRedirects }\n * @returns {Promise<{status, headers, data, text}>}\n */\nasync function fetch(url, options = {}, _depth = 0) {\n const {\n method = 'GET',\n headers = {},\n body,\n json,\n timeout = 30000,\n params,\n maxRedirects = 3,\n } = options;\n let targetUrl = url;\n if (params) {\n const u = new URL(targetUrl);\n for (const [k, v] of Object.entries(params)) u.searchParams.set(k, String(v));\n targetUrl = u.toString();\n }\n const u = new URL(targetUrl);\n const lib = u.protocol === 'https:' ? https : http;\n const reqHeaders = { 'User-Agent': 'workai-sandbox/1.0', ...headers };\n let reqBody = body;\n if (json !== undefined) {\n reqBody = JSON.stringify(json);\n reqHeaders['Content-Type'] = reqHeaders['Content-Type'] || 'application/json';\n }\n return new Promise((resolve, reject) => {\n const req = lib.request(u, { method, headers: reqHeaders, timeout }, (res) => {\n const status = res.statusCode;\n // Follow redirects (301/302/303/307/308)\n if (\n (status === 301 || status === 302 || status === 303 || status === 307 || status === 308) &&\n res.headers.location &&\n _depth < maxRedirects\n ) {\n res.resume(); // discard response body\n const nextUrl = new URL(res.headers.location, targetUrl).toString();\n const nextMethod = status === 303 ? 'GET' : method;\n const nextBody = status === 303 ? undefined : body;\n const nextJson = status === 303 ? undefined : json;\n resolve(fetch(nextUrl, { ...options, method: nextMethod, body: nextBody, json: nextJson }, _depth + 1));\n return;\n }\n const chunks = [];\n res.on('data', (c) => chunks.push(c));\n res.on('end', () => {\n const buf = Buffer.concat(chunks);\n const text = buf.toString('utf-8');\n let data = text;\n const ct = (res.headers['content-type'] || '').toLowerCase();\n if (ct.includes('application/json') || ct.includes('+json')) {\n try { data = JSON.parse(text); } catch (e) { /* keep text */ }\n }\n resolve({ status: status, headers: res.headers, data, text });\n });\n });\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(new Error('Request timeout after ' + timeout + 'ms')); });\n if (reqBody) req.write(reqBody);\n req.end();\n });\n}\n\n/** GET request shorthand */\nasync function get(url, options = {}) {\n return fetch(url, { ...options, method: 'GET' });\n}\n\n/** POST request shorthand (auto-JSON for object bodies) */\nasync function post(url, body, options = {}) {\n const isJson = typeof body === 'object' && body !== null && !Buffer.isBuffer(body);\n return fetch(url, {\n ...options,\n method: 'POST',\n json: isJson ? body : undefined,\n body: isJson ? undefined : body,\n });\n}\n\n/** PUT request shorthand (auto-JSON for object bodies) */\nasync function put(url, body, options = {}) {\n const isJson = typeof body === 'object' && body !== null && !Buffer.isBuffer(body);\n return fetch(url, {\n ...options,\n method: 'PUT',\n json: isJson ? body : undefined,\n body: isJson ? undefined : body,\n });\n}\n\n/** HEAD request shorthand */\nasync function head(url, options = {}) {\n return fetch(url, { ...options, method: 'HEAD' });\n}\n\n/** DELETE request shorthand */\nasync function del(url, options = {}) {\n return fetch(url, { ...options, method: 'DELETE' });\n}\n\n// ===== File I/O =====\n\nfunction readJson(file) {\n const content = fs.readFileSync(file, 'utf-8');\n return JSON.parse(content);\n}\n\nfunction writeJson(file, data, indent = 2) {\n const dir = path.dirname(file);\n if (dir && dir !== '.') try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}\n fs.writeFileSync(file, JSON.stringify(data, null, indent), 'utf-8');\n}\n\nfunction readText(file, encoding = 'utf-8') {\n return fs.readFileSync(file, encoding);\n}\n\nfunction writeText(file, content) {\n const dir = path.dirname(file);\n if (dir && dir !== '.') try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}\n fs.writeFileSync(file, content, 'utf-8');\n}\n\nfunction appendText(file, content) {\n const dir = path.dirname(file);\n if (dir && dir !== '.') try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}\n fs.appendFileSync(file, content, 'utf-8');\n}\n\nfunction exists(p) {\n try { return fs.existsSync(p); } catch (e) { return false; }\n}\n\nfunction listDir(dir) {\n return fs.readdirSync(dir).map(function (name) {\n let stat;\n try { stat = fs.statSync(path.join(dir, name)); } catch (e) { return name; }\n return stat.isDirectory() ? name + '/' : name;\n });\n}\n\n/**\n * readCsv - parse CSV file into array of objects\n * @param {string} file - CSV file path\n * @param {object} opts - { delimiter, headers }\n * headers: \u81EA\u5B9A\u4E49\u8868\u5934\u6570\u7EC4\uFF1B\u82E5\u63D0\u4F9B\u5219\u9996\u884C\u88AB\u89C6\u4E3A\u6570\u636E\u884C\uFF0C\u5426\u5219\u9996\u884C\u4F5C\u4E3A\u8868\u5934\n * @returns {Array<object>}\n */\nfunction readCsv(file, opts = {}) {\n const delimiter = opts.delimiter || ',';\n const content = fs.readFileSync(file, 'utf-8');\n const lines = content.split(/\\r?\\n/).filter(function (l) { return l.trim(); });\n if (lines.length === 0) return [];\n const parseLine = function (line) {\n const result = [];\n let cur = '';\n let inQuote = false;\n for (let i = 0; i < line.length; i++) {\n const c = line[i];\n if (c === '\"') {\n if (inQuote && line[i + 1] === '\"') { cur += '\"'; i++; }\n else inQuote = !inQuote;\n } else if (c === delimiter && !inQuote) {\n result.push(cur); cur = '';\n } else {\n cur += c;\n }\n }\n result.push(cur);\n return result.map(function (s) { return s.trim(); });\n };\n const headers = opts.headers || parseLine(lines[0]);\n const startIdx = opts.headers ? 0 : 1;\n const rows = [];\n for (let i = startIdx; i < lines.length; i++) {\n const values = parseLine(lines[i]);\n const row = {};\n headers.forEach(function (h, j) { row[h] = values[j] || ''; });\n rows.push(row);\n }\n return rows;\n}\n\n/**\n * writeCsv - write array of objects to CSV file\n * @param {string} file - Output CSV file path\n * @param {Array<object>} rows - Data rows\n * @param {object} opts - { headers, delimiter }\n */\nfunction writeCsv(file, rows, opts = {}) {\n if (!rows || rows.length === 0) {\n writeText(file, '');\n return;\n }\n const delimiter = opts.delimiter || ',';\n const headers = opts.headers || Object.keys(rows[0]);\n const escapeCell = function (val) {\n const s = String(val == null ? '' : val);\n if (s.includes(delimiter) || s.includes('\"') || s.includes('\\n')) {\n return '\"' + s.replace(/\"/g, '\"\"') + '\"';\n }\n return s;\n };\n const lines = [headers.map(escapeCell).join(delimiter)];\n for (const row of rows) {\n lines.push(headers.map(function (h) { return escapeCell(row[h]); }).join(delimiter));\n }\n writeText(file, lines.join('\\n'));\n}\n\n// ===== Data Utilities =====\n\n/** Calculate statistics: sum, avg, min, max, count, std */\nfunction stats(arr) {\n const nums = arr.map(Number).filter(function (n) { return !isNaN(n); });\n if (nums.length === 0) return { count: 0, sum: 0, avg: 0, min: 0, max: 0, std: 0 };\n const sumVal = nums.reduce(function (a, b) { return a + b; }, 0);\n const avgVal = sumVal / nums.length;\n const min = Math.min.apply(null, nums);\n const max = Math.max.apply(null, nums);\n const variance = nums.reduce(function (acc, n) { return acc + Math.pow(n - avgVal, 2); }, 0) / nums.length;\n return { count: nums.length, sum: sumVal, avg: avgVal, min: min, max: max, std: Math.sqrt(variance) };\n}\n\nfunction sum(arr) {\n return arr.reduce(function (a, b) { return a + (Number(b) || 0); }, 0);\n}\n\nfunction avg(arr) {\n if (arr.length === 0) return 0;\n return sum(arr) / arr.length;\n}\n\nfunction groupBy(arr, keyFn) {\n const result = {};\n for (const item of arr) {\n const key = typeof keyFn === 'function' ? keyFn(item) : item[keyFn];\n if (!result[key]) result[key] = [];\n result[key].push(item);\n }\n return result;\n}\n\nfunction sortBy(arr, keyFn, desc) {\n const fn = typeof keyFn === 'function' ? keyFn : function (x) { return x[keyFn]; };\n return arr.slice().sort(function (a, b) {\n const va = fn(a);\n const vb = fn(b);\n if (va < vb) return desc ? 1 : -1;\n if (va > vb) return desc ? -1 : 1;\n return 0;\n });\n}\n\nfunction unique(arr, keyFn) {\n if (!keyFn) {\n return arr.filter(function (v, i, self) { return self.indexOf(v) === i; });\n }\n const fn = typeof keyFn === 'function' ? keyFn : function (x) { return x[keyFn]; };\n const seen = new Set();\n return arr.filter(function (x) {\n const k = fn(x);\n if (seen.has(k)) return false;\n seen.add(k);\n return true;\n });\n}\n\nfunction chunk(arr, size) {\n size = Math.max(1, size || 1);\n const result = [];\n for (let i = 0; i < arr.length; i += size) {\n result.push(arr.slice(i, i + size));\n }\n return result;\n}\n\nfunction range(start, end, step) {\n step = step || 1;\n if (end === undefined) { end = start; start = 0; }\n const result = [];\n if (step > 0) {\n for (let i = start; i < end; i += step) result.push(i);\n } else {\n for (let i = start; i > end; i += step) result.push(i);\n }\n return result;\n}\n\nfunction pick(obj, keys) {\n const result = {};\n for (const k of keys) {\n if (k in obj) result[k] = obj[k];\n }\n return result;\n}\n\nfunction omit(obj, keys) {\n const keySet = new Set(keys);\n const result = {};\n for (const k of Object.keys(obj)) {\n if (!keySet.has(k)) result[k] = obj[k];\n }\n return result;\n}\n\nfunction flatten(arr) {\n return arr.reduce(function (flat, sub) { return flat.concat(Array.isArray(sub) ? sub : [sub]); }, []);\n}\n\n// ===== Date Utilities =====\n\nfunction formatDate(date, format) {\n const d = date instanceof Date ? date : new Date(date);\n if (isNaN(d.getTime())) return 'Invalid Date';\n const pad = function (n) { return n < 10 ? '0' + n : '' + n; };\n const map = {\n YYYY: d.getFullYear(),\n MM: pad(d.getMonth() + 1),\n DD: pad(d.getDate()),\n HH: pad(d.getHours()),\n mm: pad(d.getMinutes()),\n ss: pad(d.getSeconds()),\n };\n let result = format || 'YYYY-MM-DD HH:mm:ss';\n for (const k in map) {\n result = result.replace(k, map[k]);\n }\n return result;\n}\n\nfunction parseDate(str) {\n if (typeof str === 'number') return new Date(str);\n const d = new Date(str);\n if (!isNaN(d.getTime())) return d;\n const m = String(str).match(/^(\\d{4})[-\\/](\\d{1,2})[-\\/](\\d{1,2})/);\n if (m) return new Date(parseInt(m[1], 10), parseInt(m[2], 10) - 1, parseInt(m[3], 10));\n return null;\n}\n\nfunction now() {\n return new Date().toISOString();\n}\n\nfunction daysAgo(n) {\n const d = new Date();\n d.setDate(d.getDate() - n);\n return d;\n}\n\nfunction daysLater(n) {\n const d = new Date();\n d.setDate(d.getDate() + n);\n return d;\n}\n\nfunction dateDiff(d1, d2, unit) {\n const date1 = d1 instanceof Date ? d1 : new Date(d1);\n const date2 = d2 instanceof Date ? d2 : new Date(d2);\n const diffMs = Math.abs(date2.getTime() - date1.getTime());\n unit = unit || 'days';\n switch (unit) {\n case 'seconds': return Math.floor(diffMs / 1000);\n case 'minutes': return Math.floor(diffMs / 60000);\n case 'hours': return Math.floor(diffMs / 3600000);\n case 'days': return Math.floor(diffMs / 86400000);\n default: return diffMs;\n }\n}\n\n// ===== String Utilities =====\n\n/**\n * template - Simple template interpolation\n * @param {string} str - Template string with {variable} or {a.b.c} placeholders\n * @param {object} data - Data object\n * @returns {string}\n */\nfunction template(str, data) {\n return str.replace(/\\{([^}]+)\\}/g, function (match, key) {\n const value = key.trim().split('.').reduce(function (obj, k) {\n return obj && obj[k] !== undefined ? obj[k] : undefined;\n }, data);\n return value !== undefined && value !== null ? String(value) : '';\n });\n}\n\nfunction slugify(str) {\n return String(str)\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\nfunction truncate(str, len, suffix) {\n if (String(str).length <= len) return String(str);\n return String(str).substring(0, len) + (suffix || '...');\n}\n\nfunction pad(str, len, char, right) {\n str = String(str);\n char = char || ' ';\n const diff = len - str.length;\n if (diff <= 0) return str;\n const padding = char.repeat(diff);\n return right ? str + padding : padding + str;\n}\n\n// ===== Table Generators =====\n\n/**\n * markdownTable - Generate markdown table from array of objects\n * @param {Array<object>} rows - Data rows\n * @param {Array<string>} headers - Optional custom headers (defaults to Object.keys of first row)\n * @returns {string} Markdown table string\n */\nfunction markdownTable(rows, headers) {\n if (!rows || rows.length === 0) return '';\n headers = headers || Object.keys(rows[0]);\n const lines = [];\n lines.push('| ' + headers.join(' | ') + ' |');\n lines.push('| ' + headers.map(function () { return '---'; }).join(' | ') + ' |');\n for (const row of rows) {\n lines.push('| ' + headers.map(function (h) {\n return String(row[h] == null ? '' : row[h]).replace(/\\|/g, '\\\\|');\n }).join(' | ') + ' |');\n }\n return lines.join('\\n');\n}\n\n/**\n * htmlTable - Generate HTML table from array of objects\n * @param {Array<object>} rows - Data rows\n * @param {object} opts - { headers, tableClass }\n * @returns {string} HTML table string\n */\nfunction htmlTable(rows, opts = {}) {\n if (!rows || rows.length === 0) return '<table><tbody></tbody></table>';\n const headers = opts.headers || Object.keys(rows[0]);\n const tableClass = opts.tableClass ? ' class=\"' + opts.tableClass + '\"' : '';\n const parts = ['<table' + tableClass + '>'];\n parts.push('<thead><tr>');\n for (const h of headers) {\n parts.push('<th>' + h + '</th>');\n }\n parts.push('</tr></thead><tbody>');\n for (const row of rows) {\n parts.push('<tr>');\n for (const h of headers) {\n parts.push('<td>' + String(row[h] == null ? '' : row[h]) + '</td>');\n }\n parts.push('</tr>');\n }\n parts.push('</tbody></table>');\n return parts.join('');\n}\n\n// ===== Logger =====\n\nconst log = {\n info: function (msg, meta) { console.log('[INFO] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n warn: function (msg, meta) { console.warn('[WARN] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n error: function (msg, meta) { console.error('[ERROR] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n debug: function (msg, meta) { console.log('[DEBUG] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },\n};\n\n// ===== Util =====\n\nfunction sleep(ms) {\n return new Promise(function (resolve) { setTimeout(resolve, ms); });\n}\n\nfunction uuid() {\n return require('crypto').randomUUID();\n}\n\nfunction hash(value, algo) {\n return require('crypto').createHash(algo || 'sha256').update(String(value)).digest('hex');\n}\n\nfunction randomInt(minValue, maxValue) {\n minValue = minValue === undefined ? 0 : minValue;\n maxValue = maxValue === undefined ? 100 : maxValue;\n return Math.floor(Math.random() * (maxValue - minValue + 1)) + minValue;\n}\n\nfunction randomFloat(minValue, maxValue) {\n minValue = minValue === undefined ? 0 : minValue;\n maxValue = maxValue === undefined ? 1 : maxValue;\n return Math.random() * (maxValue - minValue) + minValue;\n}\n\nfunction randomChoice(seq) {\n if (!Array.isArray(seq)) throw new Error('randomChoice \u9700\u8981\u6570\u7EC4');\n return seq[Math.floor(Math.random() * seq.length)];\n}\n\n// \u5185\u5B58\u7F13\u5B58\uFF08\u5E26 TTL\uFF0C\u5355\u4F4D\u79D2\uFF09\uFF0Csb.cache(key, ttl).get(factory)\nconst _cacheStore = {};\nfunction cache(key, ttl) {\n return {\n get: function (factory) {\n const nowTs = Date.now();\n const entry = _cacheStore[key];\n if (entry && (entry.expireAt === null || entry.expireAt > nowTs)) return entry.value;\n const value = typeof factory === 'function' ? factory() : factory;\n _cacheStore[key] = { value: value, expireAt: ttl ? nowTs + ttl * 1000 : null };\n return value;\n },\n clear: function () { delete _cacheStore[key]; },\n };\n}\n\n// ===== Core exports =====\n\nconst _exports = {\n // HTTP\n fetch: fetch,\n get: get,\n post: post,\n put: put,\n head: head,\n del: del,\n // File I/O\n readJson: readJson,\n writeJson: writeJson,\n readText: readText,\n writeText: writeText,\n appendText: appendText,\n readCsv: readCsv,\n writeCsv: writeCsv,\n exists: exists,\n listDir: listDir,\n // Data\n stats: stats,\n sum: sum,\n avg: avg,\n groupBy: groupBy,\n sortBy: sortBy,\n unique: unique,\n chunk: chunk,\n range: range,\n pick: pick,\n omit: omit,\n flatten: flatten,\n // Date\n formatDate: formatDate,\n parseDate: parseDate,\n now: now,\n daysAgo: daysAgo,\n daysLater: daysLater,\n dateDiff: dateDiff,\n // String\n template: template,\n slugify: slugify,\n truncate: truncate,\n pad: pad,\n // Table\n markdownTable: markdownTable,\n htmlTable: htmlTable,\n // Logger\n log: log,\n // Util\n sleep: sleep,\n uuid: uuid,\n hash: hash,\n randomInt: randomInt,\n randomFloat: randomFloat,\n randomChoice: randomChoice,\n cache: cache,\n // fs/path passthrough for convenience\n fs: fs,\n path: path,\n};\n\nmodule.exports = _exports;\n\n// ===== Load extensions from _prelude_ext/ =====\n// \u6269\u5C55\u6A21\u5757\u901A\u8FC7 module.exports \u5BFC\u51FA\u5BF9\u8C61\uFF0C\u52A0\u8F7D\u65F6\u5408\u5E76\u8FDB sb\uFF08\u540C\u540D\u8986\u76D6\u6838\u5FC3\uFF0C\u4FBF\u4E8E\u5B9A\u5236\uFF09\n(function loadPreludeExtensions() {\n try {\n const extDir = path.join(__dirname, '_prelude_ext');\n if (!fs.existsSync(extDir)) return;\n const extFiles = fs.readdirSync(extDir).filter(function (f) {\n return f.endsWith('.cjs') && f !== 'index.cjs';\n });\n for (const f of extFiles) {\n try {\n const mod = require(path.join(extDir, f));\n const ext = mod && mod.__esModule && mod.default ? mod.default : mod;\n if (ext && typeof ext === 'object') {\n for (const key of Object.keys(ext)) {\n _exports[key] = ext[key];\n }\n }\n } catch (e) {\n console.warn('[prelude] Failed to load extension \"' + f + '\": ' + (e && e.message));\n }\n }\n } catch (e) { /* ignore extension load errors */ }\n})();\n";
|
|
54
54
|
//# sourceMappingURL=sandbox-prelude.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-prelude.d.ts","sourceRoot":"","sources":["../../../src/sandbox/sandbox-prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,MAAM,WAAW,uBAAuB;IACtC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAalF;AAED,kBAAkB;AAClB,wBAAgB,2BAA2B,IAAI,uBAAuB,EAAE,CAEvE;AAED,yBAAyB;AACzB,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"sandbox-prelude.d.ts","sourceRoot":"","sources":["../../../src/sandbox/sandbox-prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,MAAM,WAAW,uBAAuB;IACtC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAalF;AAED,kBAAkB;AAClB,wBAAgB,2BAA2B,IAAI,uBAAuB,EAAE,CAEvE;AAED,yBAAyB;AACzB,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,uwmBAmnBlC,CAAC"}
|
|
@@ -561,6 +561,53 @@ const log = {
|
|
|
561
561
|
debug: function (msg, meta) { console.log('[DEBUG] ' + msg + (meta !== undefined ? ' ' + _safeStringify(meta) : '')); },
|
|
562
562
|
};
|
|
563
563
|
|
|
564
|
+
// ===== Util =====
|
|
565
|
+
|
|
566
|
+
function sleep(ms) {
|
|
567
|
+
return new Promise(function (resolve) { setTimeout(resolve, ms); });
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
function uuid() {
|
|
571
|
+
return require('crypto').randomUUID();
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function hash(value, algo) {
|
|
575
|
+
return require('crypto').createHash(algo || 'sha256').update(String(value)).digest('hex');
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function randomInt(minValue, maxValue) {
|
|
579
|
+
minValue = minValue === undefined ? 0 : minValue;
|
|
580
|
+
maxValue = maxValue === undefined ? 100 : maxValue;
|
|
581
|
+
return Math.floor(Math.random() * (maxValue - minValue + 1)) + minValue;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
function randomFloat(minValue, maxValue) {
|
|
585
|
+
minValue = minValue === undefined ? 0 : minValue;
|
|
586
|
+
maxValue = maxValue === undefined ? 1 : maxValue;
|
|
587
|
+
return Math.random() * (maxValue - minValue) + minValue;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function randomChoice(seq) {
|
|
591
|
+
if (!Array.isArray(seq)) throw new Error('randomChoice 需要数组');
|
|
592
|
+
return seq[Math.floor(Math.random() * seq.length)];
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// 内存缓存(带 TTL,单位秒),sb.cache(key, ttl).get(factory)
|
|
596
|
+
const _cacheStore = {};
|
|
597
|
+
function cache(key, ttl) {
|
|
598
|
+
return {
|
|
599
|
+
get: function (factory) {
|
|
600
|
+
const nowTs = Date.now();
|
|
601
|
+
const entry = _cacheStore[key];
|
|
602
|
+
if (entry && (entry.expireAt === null || entry.expireAt > nowTs)) return entry.value;
|
|
603
|
+
const value = typeof factory === 'function' ? factory() : factory;
|
|
604
|
+
_cacheStore[key] = { value: value, expireAt: ttl ? nowTs + ttl * 1000 : null };
|
|
605
|
+
return value;
|
|
606
|
+
},
|
|
607
|
+
clear: function () { delete _cacheStore[key]; },
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
|
|
564
611
|
// ===== Core exports =====
|
|
565
612
|
|
|
566
613
|
const _exports = {
|
|
@@ -610,6 +657,14 @@ const _exports = {
|
|
|
610
657
|
htmlTable: htmlTable,
|
|
611
658
|
// Logger
|
|
612
659
|
log: log,
|
|
660
|
+
// Util
|
|
661
|
+
sleep: sleep,
|
|
662
|
+
uuid: uuid,
|
|
663
|
+
hash: hash,
|
|
664
|
+
randomInt: randomInt,
|
|
665
|
+
randomFloat: randomFloat,
|
|
666
|
+
randomChoice: randomChoice,
|
|
667
|
+
cache: cache,
|
|
613
668
|
// fs/path passthrough for convenience
|
|
614
669
|
fs: fs,
|
|
615
670
|
path: path,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-prelude.js","sourceRoot":"","sources":["../../../src/sandbox/sandbox-prelude.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;;AAoBH,0EAaC;AAGD,kEAEC;AAGD,sEAEC;AAhCD,MAAM,0BAA0B,GAA8B,EAAE,CAAC;AAEjE;;;;;;GAMG;AACH,SAAgB,+BAA+B,CAAC,IAAY,EAAE,MAAc;IAC1E,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,gCAAgC,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,sCAAsC,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,GAAG,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACzE,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACb,0BAA0B,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,0BAA0B,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,kBAAkB;AAClB,SAAgB,2BAA2B;IACzC,OAAO,0BAA0B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,yBAAyB;AACzB,SAAgB,6BAA6B;IAC3C,0BAA0B,CAAC,MAAM,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACU,QAAA,sBAAsB,GAAG
|
|
1
|
+
{"version":3,"file":"sandbox-prelude.js","sourceRoot":"","sources":["../../../src/sandbox/sandbox-prelude.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;;AAoBH,0EAaC;AAGD,kEAEC;AAGD,sEAEC;AAhCD,MAAM,0BAA0B,GAA8B,EAAE,CAAC;AAEjE;;;;;;GAMG;AACH,SAAgB,+BAA+B,CAAC,IAAY,EAAE,MAAc;IAC1E,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,gCAAgC,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,sCAAsC,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,GAAG,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACzE,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACb,0BAA0B,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,0BAA0B,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,kBAAkB;AAClB,SAAgB,2BAA2B;IACzC,OAAO,0BAA0B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,yBAAyB;AACzB,SAAgB,6BAA6B;IAC3C,0BAA0B,CAAC,MAAM,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACU,QAAA,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmnBrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-task-runtime.d.ts","sourceRoot":"","sources":["../../../src/automation/node-task-runtime.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAoC,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAEzG,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,6BAA6B,CAAC;CACjD;AAaD,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;gBAEpD,OAAO,GAAE,4BAAiC;IAKhD,OAAO,CACX,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,6BAA6B,CAAC;IAqEzC;;;OAGG;IACG,aAAa,CACjB,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,EACjC,SAAS,GAAE;QACT,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;QAChD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACnC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,6BAA6B,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAChC,GACL,OAAO,CAAC,6BAA6B,CAAC;IAyEzC,8CAA8C;IAC9C,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,oBAAoB;
|
|
1
|
+
{"version":3,"file":"node-task-runtime.d.ts","sourceRoot":"","sources":["../../../src/automation/node-task-runtime.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAoC,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAEzG,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,6BAA6B,CAAC;CACjD;AAaD,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;gBAEpD,OAAO,GAAE,4BAAiC;IAKhD,OAAO,CACX,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,6BAA6B,CAAC;IAqEzC;;;OAGG;IACG,aAAa,CACjB,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,wBAAwB,EACjC,SAAS,GAAE;QACT,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;QAChD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACnC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,6BAA6B,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAChC,GACL,OAAO,CAAC,6BAA6B,CAAC;IAyEzC,8CAA8C;IAC9C,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,oBAAoB;IAwU5B,+CAA+C;IAC/C,OAAO,CAAC,cAAc;IAqBtB,gEAAgE;IAChE,OAAO,CAAC,YAAY;IASpB,wDAAwD;IACxD,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,kBAAkB;CAgB3B;AAID,wBAAgB,8BAA8B,IAAI,2BAA2B,CAG5E"}
|