sync: update from private repo (0e09596)
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync
2026-06-08 03:23:19 +00:00
parent 03be80f036
commit 0f75bdfbab
10 changed files with 256 additions and 38 deletions
+19 -9
View File
@@ -7,9 +7,16 @@ import { logger } from './logger.js';
import { loadConfig } from './config.js';
import { resolveAndRunUserScript } from './user-folder/script-orchestrator.js';
// 進行中とみなすステータス(これらの場合はスキップ)
// 進行中とみなすステータス(これらの場合は次回スケジュール実行をスキップ)
// これらはいずれも「真に実行中」か「自動回復する一時状態」のみ:
// queued/dispatching/running … 実行中
// waiting_subtasks … 並列サブタスク完了待ち。requeueWaitingSubtasks が自動回復させる
// waiting_human (ASK) は意図的に含めない。自動回復もタイムアウトも無いため、
// 無人実行のスケジュールタスクが一度 ASK を出すとその後の実行が永久にスキップされ、
// スケジュールが事実上死ぬ。各スケジュール実行は独立した新規タスクなので、
// 前回の waiting_human タスクは残置し(ユーザーが後から回答 or 放置できる)、新規実行を走らせる。
const IN_PROGRESS_STATUSES = new Set([
'queued', 'dispatching', 'running', 'waiting_human', 'waiting_subtasks',
'queued', 'dispatching', 'running', 'waiting_subtasks',
]);
export interface ScheduleInput {
@@ -295,9 +302,12 @@ export class Scheduler {
if (!this.userFolderRoot) {
throw new Error(`scheduled_task=${item.id}: task_kind='script' but Scheduler.userFolderRoot was not configured`);
}
if (!item.ownerId) {
throw new Error(`scheduled_task=${item.id}: task_kind='script' requires an owner_id (scripts are per-user)`);
}
// No-auth mode stores scheduled tasks with ownerId=null (scheduled-tasks-api
// has no authenticated user). Scripts are per-user (data/users/{id}/scripts/),
// so resolve to the same 'local' namespace the RunUserScript tool uses in
// no-auth (ctx.userId='local'). In auth mode item.ownerId is always set, so
// scriptOwner === item.ownerId and behaviour is unchanged.
const scriptOwner = item.ownerId ?? 'local';
// Same security gates as the LLM-facing RunUserScript tool: global config
// toggle + optional per-user allowlist. A scheduled run is automated, so a
@@ -308,9 +318,9 @@ export class Scheduler {
`scheduled_task=${item.id}: user scripts are disabled (tools.user_scripts_enabled=false)`,
);
}
if (Array.isArray(gate.allowUserids) && gate.allowUserids.length > 0 && !gate.allowUserids.includes(item.ownerId)) {
if (Array.isArray(gate.allowUserids) && gate.allowUserids.length > 0 && !gate.allowUserids.includes(scriptOwner)) {
throw new Error(
`scheduled_task=${item.id}: owner "${item.ownerId}" is not in tools.user_scripts_allow_userids`,
`scheduled_task=${item.id}: owner "${scriptOwner}" is not in tools.user_scripts_allow_userids`,
);
}
@@ -375,7 +385,7 @@ export class Scheduler {
try {
const runResult = await resolveAndRunUserScript({
rootDir: this.userFolderRoot,
userId: item.ownerId,
userId: scriptOwner,
name: item.scriptName,
params,
sessRepo: this.sessRepo,
@@ -417,7 +427,7 @@ export class Scheduler {
await this.repo.addAuditLog(job.id, 'user_script_run', 'scheduler', {
scheduledTaskId: item.id,
userId: item.ownerId,
userId: scriptOwner,
scriptName: item.scriptName,
ok: !runFailed,
...(runFailed && errorMessage ? { error: errorMessage.slice(0, 500) } : {}),