@linxin666/dsh-client-ui-task-board 0.4.5 → 0.4.6
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/README.i18n.yaml +2 -2
- package/README.md +20 -12
- package/README.zh.md +20 -12
- package/lib/client.js +1327 -229
- package/lib/client.js.map +1 -1
- package/lib/index.js +1909 -348
- package/lib/types/client/TaskBoardSettingsCard.d.ts +12 -0
- package/lib/types/client/index.d.ts +4 -5
- package/lib/types/client/locales.d.ts +65 -0
- package/lib/types/client/plugin-card-seat.d.ts +5 -0
- package/lib/types/client/schedule-zone.d.ts +50 -0
- package/lib/types/core/controller.d.ts +10 -11
- package/lib/types/core/poll-cadence.d.ts +31 -0
- package/lib/types/core/tasks.d.ts +144 -14
- package/lib/types/core/use-cases/task-schedule.d.ts +68 -10
- package/lib/types/core/verification-budget.d.ts +52 -0
- package/lib/types/core/verification.d.ts +376 -9
- package/lib/types/host/verification-gate.d.ts +24 -0
- package/lib/types/host/verification-runner.d.ts +38 -7
- package/lib/types/host-ledger.d.ts +82 -7
- package/lib/types/host-runner.d.ts +32 -9
- package/lib/types/host-service.d.ts +117 -9
- package/lib/types/index.d.ts +54 -0
- package/lib/types/protocol.d.ts +50 -12
- package/package.json +2 -6
- package/src/client/TaskBoardSettingsCard.tsx +74 -1
- package/src/client/board/NewTaskModal.tsx +151 -20
- package/src/client/board/TaskCard.tsx +3 -3
- package/src/client/board/TaskDetail.tsx +219 -18
- package/src/client/board/VerificationReport.tsx +132 -13
- package/src/client/board/status-key.ts +3 -0
- package/src/client/index.ts +43 -50
- package/src/client/locales.ts +137 -4
- package/src/client/plugin-card-seat.ts +7 -0
- package/src/client/schedule-zone.ts +100 -2
- package/src/core/controller.ts +12 -8
- package/src/core/poll-cadence.ts +41 -0
- package/src/core/store.ts +64 -15
- package/src/core/tasks.ts +193 -39
- package/src/core/use-cases/task-create.ts +30 -9
- package/src/core/use-cases/task-schedule.ts +190 -25
- package/src/core/use-cases/task-update.ts +3 -3
- package/src/core/verification-budget.ts +115 -0
- package/src/core/verification.ts +785 -17
- package/src/host/agent-tools.ts +106 -21
- package/src/host/verification-gate.ts +172 -16
- package/src/host/verification-runner.ts +207 -40
- package/src/host-ledger.ts +328 -42
- package/src/host-runner.ts +52 -19
- package/src/host-service.ts +299 -36
- package/src/index.ts +101 -5
- package/src/protocol.ts +132 -28
- package/lib/invariant.js +0 -6
- package/lib/types/client/board-card-seat.d.ts +0 -34
- package/lib/types/invariant.d.ts +0 -3
- package/src/client/board-card-seat.ts +0 -102
- package/src/invariant.ts +0 -4
package/src/host-runner.ts
CHANGED
|
@@ -159,12 +159,12 @@ export interface PromptContext {
|
|
|
159
159
|
/** True when those members run as teammates inside this session (Team Lead). */
|
|
160
160
|
team?: boolean
|
|
161
161
|
/**
|
|
162
|
-
* Scheduled-run provenance: the instant the
|
|
163
|
-
* IANA zone its wall clock was read in. Present only for a
|
|
164
|
-
* run, so the model can resolve an unqualified date in the
|
|
165
|
-
* instead of guessing from the Host clock (issue #1722).
|
|
162
|
+
* Scheduled-run provenance: the instant the rule actually fired, its kind,
|
|
163
|
+
* and the IANA zone its wall clock was read in. Present only for a
|
|
164
|
+
* timer-triggered run, so the model can resolve an unqualified date in the
|
|
165
|
+
* run's own terms instead of guessing from the Host clock (issue #1722).
|
|
166
166
|
*/
|
|
167
|
-
schedule?: { triggeredAt: number; timeZone: string;
|
|
167
|
+
schedule?: { triggeredAt: number; timeZone: string; mode: 'cron' | 'once'; cron?: string }
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
/**
|
|
@@ -184,16 +184,20 @@ function peerPromptPreamble(context: PromptContext): string | undefined {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
|
-
* The scheduled-run section: this execution was triggered by the card's
|
|
188
|
-
*
|
|
189
|
-
* and the rule text, so the run's own clock is unambiguous — the board's
|
|
187
|
+
* The scheduled-run section: this execution was triggered by the card's
|
|
188
|
+
* schedule rather than by a person. It states the firing instant, the rule's
|
|
189
|
+
* zone, and the rule text, so the run's own clock is unambiguous — the board's
|
|
190
190
|
* scheduler fires on a wall clock in a specific IANA zone, which is not
|
|
191
|
-
* necessarily the zone of whatever session the run lands in.
|
|
191
|
+
* necessarily the zone of whatever session the run lands in. A one-shot says
|
|
192
|
+
* so explicitly, so the run does not expect a recurrence.
|
|
192
193
|
*/
|
|
193
194
|
function schedulePromptPreamble(context: PromptContext): string | undefined {
|
|
194
195
|
const schedule = context.schedule
|
|
195
196
|
if (schedule === undefined) return undefined
|
|
196
197
|
const stamp = new Date(schedule.triggeredAt).toISOString()
|
|
198
|
+
if (schedule.mode === 'once') {
|
|
199
|
+
return `本次执行由任务看板的单次定时自动触发:计划时间 ${stamp}(UTC),时区 ${schedule.timeZone}。这是一次性计划,本次执行之后该卡片不会再自动执行。需要判断「今天」「现在」或计算时间窗口时,以该时区的触发时间为准。`
|
|
200
|
+
}
|
|
197
201
|
return `本次执行由任务看板的定时规则自动触发:触发时间 ${stamp}(UTC),规则时区 ${schedule.timeZone},cron 表达式 ${schedule.cron}。需要判断「今天」「现在」或计算时间窗口时,以该时区的触发时间为准。`
|
|
198
202
|
}
|
|
199
203
|
|
|
@@ -356,7 +360,24 @@ export class HostExecutionRunner {
|
|
|
356
360
|
* @param options - optional session to continue in.
|
|
357
361
|
* @returns the session id the execution runs in.
|
|
358
362
|
*/
|
|
359
|
-
async launch(task: TaskRecord, options: {
|
|
363
|
+
async launch(task: TaskRecord, options: {
|
|
364
|
+
reuseSessionId?: string
|
|
365
|
+
promptContext?: PromptContext
|
|
366
|
+
onSession?: (sessionId: string) => void
|
|
367
|
+
onGoalArmed?: (armed: boolean) => void
|
|
368
|
+
/**
|
|
369
|
+
* GLOBAL native /goal switch, resolved by the caller ONCE per execution and
|
|
370
|
+
* carried here so the decision is frozen for this launch.
|
|
371
|
+
*
|
|
372
|
+
* Frozen deliberately: a settings edit made while the run is in flight must
|
|
373
|
+
* not arm, disarm or otherwise change the goal/acceptance contract of a run
|
|
374
|
+
* already running. Absent means off — the default for every deployment that
|
|
375
|
+
* never touched the switch, including cards written before the option
|
|
376
|
+
* existed. A plain single turn is what an off switch produces; the task-level
|
|
377
|
+
* `goalRun` still applies on top of it (both must ASK for a goal).
|
|
378
|
+
*/
|
|
379
|
+
goalEnabled?: boolean
|
|
380
|
+
} = {}): Promise<string> {
|
|
360
381
|
// A handover bundle overrides the legacy pin fields: the bundle is the
|
|
361
382
|
// authoritative execution triplet for a continuation card (issue #5). A
|
|
362
383
|
// card that pins nothing is resolved to the deployment's most recently used
|
|
@@ -396,7 +417,7 @@ export class HostExecutionRunner {
|
|
|
396
417
|
// at the gate without its binding.
|
|
397
418
|
options.onSession?.(reused)
|
|
398
419
|
await this.assertReusedPreset(reused, mode)
|
|
399
|
-
await this.pinAndPrompt(reused, task, permission, options.promptContext, options.onGoalArmed)
|
|
420
|
+
await this.pinAndPrompt(reused, task, permission, options.promptContext, options.onGoalArmed, options.goalEnabled === true)
|
|
400
421
|
} catch (error) {
|
|
401
422
|
throw new SessionLaunchError(reused, error)
|
|
402
423
|
}
|
|
@@ -410,7 +431,7 @@ export class HostExecutionRunner {
|
|
|
410
431
|
options.onSession?.(sessionId)
|
|
411
432
|
try {
|
|
412
433
|
await this.invoke('session', 'rename', { sessionId, title: task.title })
|
|
413
|
-
await this.pinAndPrompt(sessionId, task, permission, options.promptContext, options.onGoalArmed)
|
|
434
|
+
await this.pinAndPrompt(sessionId, task, permission, options.promptContext, options.onGoalArmed, options.goalEnabled === true)
|
|
414
435
|
} catch (error) {
|
|
415
436
|
throw new SessionLaunchError(sessionId, error)
|
|
416
437
|
}
|
|
@@ -456,6 +477,7 @@ export class HostExecutionRunner {
|
|
|
456
477
|
permission: TaskPermission | undefined,
|
|
457
478
|
context: PromptContext = {},
|
|
458
479
|
onGoalArmed?: (armed: boolean) => void,
|
|
480
|
+
goalEnabled = false,
|
|
459
481
|
): Promise<void> {
|
|
460
482
|
if (permission !== undefined) {
|
|
461
483
|
if (this.commands === undefined) throw new Error('permission command dispatcher is unavailable')
|
|
@@ -484,7 +506,7 @@ export class HostExecutionRunner {
|
|
|
484
506
|
mode: 'queue' as const,
|
|
485
507
|
content: [{ type: 'text' as const, text: promptText(task, context) }],
|
|
486
508
|
})
|
|
487
|
-
const armed = await this.armGoal(sessionId, task, context)
|
|
509
|
+
const armed = await this.armGoal(sessionId, task, context, goalEnabled)
|
|
488
510
|
onGoalArmed?.(armed)
|
|
489
511
|
}
|
|
490
512
|
|
|
@@ -512,14 +534,25 @@ export class HostExecutionRunner {
|
|
|
512
534
|
* dsh's goal-round driver keeps starting continuation rounds until the agent
|
|
513
535
|
* marks it complete (see {@link goalVerdict} for how the run settles).
|
|
514
536
|
*
|
|
515
|
-
*
|
|
537
|
+
* Two switches gate the arming, and BOTH must ask for it:
|
|
538
|
+
* - the GLOBAL native-/goal switch (`goalEnabled`, default OFF), frozen when
|
|
539
|
+
* this execution started; and
|
|
540
|
+
* - the task's own `goalRun` (absent means off, only an explicit true opts
|
|
541
|
+
* the card into a goal run).
|
|
542
|
+
*
|
|
516
543
|
* A refusal (no command dispatcher, no `/goal` command in this cohort, an
|
|
517
|
-
* objective the command rejects) is reported and the run continues as
|
|
518
|
-
*
|
|
519
|
-
*
|
|
544
|
+
* objective the command rejects) is reported and the run continues as a plain
|
|
545
|
+
* turn: the task was asked to run, and a missing goal mode must not lose the
|
|
546
|
+
* work.
|
|
547
|
+
* @param sessionId - the session to arm in.
|
|
548
|
+
* @param task - the task being run.
|
|
549
|
+
* @param context - the run's prompt context.
|
|
550
|
+
* @param goalEnabled - the GLOBAL switch, frozen for this execution.
|
|
551
|
+
* @returns whether `/goal` was really armed.
|
|
520
552
|
*/
|
|
521
|
-
private async armGoal(sessionId: ExecutionSessionId, task: TaskRecord, context: PromptContext): Promise<boolean> {
|
|
522
|
-
if (
|
|
553
|
+
private async armGoal(sessionId: ExecutionSessionId, task: TaskRecord, context: PromptContext, goalEnabled: boolean): Promise<boolean> {
|
|
554
|
+
if (!goalEnabled) return false
|
|
555
|
+
if (task.goalRun !== true) return false
|
|
523
556
|
if (this.commands === undefined) {
|
|
524
557
|
console.warn('[dsh-task-board] no command dispatcher is available; task ' + task.id + ' runs without /goal')
|
|
525
558
|
return false
|