@qlingzzy/qling 1.0.0 → 1.1.0
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/CHANGELOG.md +154 -0
- package/README.en.md +82 -17
- package/README.md +15 -7
- package/dist/agent/main-loop.d.ts +120 -0
- package/dist/agent/main-loop.d.ts.map +1 -0
- package/dist/agent/main-loop.js +279 -0
- package/dist/agent/subtask-parallel.d.ts +29 -0
- package/dist/agent/subtask-parallel.d.ts.map +1 -0
- package/dist/agent/subtask-parallel.js +107 -0
- package/dist/agent/subtask.d.ts +13 -0
- package/dist/agent/subtask.d.ts.map +1 -1
- package/dist/agent/subtask.js +79 -24
- package/dist/agent/system-prompt.d.ts +39 -0
- package/dist/agent/system-prompt.d.ts.map +1 -0
- package/dist/agent/system-prompt.js +89 -0
- package/dist/agent/tool-orchestrator.d.ts +66 -0
- package/dist/agent/tool-orchestrator.d.ts.map +1 -0
- package/dist/agent/tool-orchestrator.js +355 -0
- package/dist/agent-loop.d.ts +29 -16
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +262 -807
- package/dist/agents/roles.d.ts +57 -0
- package/dist/agents/roles.d.ts.map +1 -0
- package/dist/agents/roles.js +198 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +17 -3
- package/dist/commands/claude-style.d.ts.map +1 -1
- package/dist/commands/claude-style.js +19 -10
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +3 -2
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +6 -0
- package/dist/commands/mode.d.ts +16 -0
- package/dist/commands/mode.d.ts.map +1 -0
- package/dist/commands/mode.js +67 -0
- package/dist/commands/recover.d.ts +3 -0
- package/dist/commands/recover.d.ts.map +1 -0
- package/dist/commands/recover.js +69 -0
- package/dist/commands/runtime.d.ts +2 -0
- package/dist/commands/runtime.d.ts.map +1 -1
- package/dist/commands/runtime.js +2 -0
- package/dist/commands/trace.d.ts +3 -0
- package/dist/commands/trace.d.ts.map +1 -0
- package/dist/commands/trace.js +45 -0
- package/dist/commands/verify.js +2 -2
- package/dist/config-report.d.ts +0 -1
- package/dist/config-report.d.ts.map +1 -1
- package/dist/config-report.js +1 -2
- package/dist/config.d.ts +0 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -1
- package/dist/context-report.d.ts +13 -7
- package/dist/context-report.d.ts.map +1 -1
- package/dist/context-report.js +64 -61
- package/dist/context-tool-hygiene.d.ts +36 -0
- package/dist/context-tool-hygiene.d.ts.map +1 -0
- package/dist/context-tool-hygiene.js +125 -0
- package/dist/dashboard/client.d.ts +2 -0
- package/dist/dashboard/client.d.ts.map +1 -0
- package/dist/dashboard/client.js +305 -0
- package/dist/dashboard/model.d.ts +13 -0
- package/dist/dashboard/model.d.ts.map +1 -0
- package/dist/dashboard/model.js +112 -0
- package/dist/dashboard/page.d.ts +3 -0
- package/dist/dashboard/page.d.ts.map +1 -0
- package/dist/dashboard/page.js +204 -0
- package/dist/dashboard/types.d.ts +63 -0
- package/dist/dashboard/types.d.ts.map +1 -0
- package/dist/dashboard/types.js +1 -0
- package/dist/dashboard-server.d.ts +24 -4
- package/dist/dashboard-server.d.ts.map +1 -1
- package/dist/dashboard-server.js +397 -302
- package/dist/discovery-registry.d.ts +17 -3
- package/dist/discovery-registry.d.ts.map +1 -1
- package/dist/discovery-registry.js +78 -3
- package/dist/doctor.d.ts +8 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +116 -0
- package/dist/eval/llm-tasks.d.ts +5 -0
- package/dist/eval/llm-tasks.d.ts.map +1 -0
- package/dist/eval/llm-tasks.js +125 -0
- package/dist/eval/repo-tasks.d.ts +12 -0
- package/dist/eval/repo-tasks.d.ts.map +1 -0
- package/dist/eval/repo-tasks.js +220 -0
- package/dist/eval/runner.d.ts +3 -1
- package/dist/eval/runner.d.ts.map +1 -1
- package/dist/eval/runner.js +23 -4
- package/dist/eval/tasks.d.ts.map +1 -1
- package/dist/eval/tasks.js +186 -0
- package/dist/eval/types.d.ts +8 -5
- package/dist/eval/types.d.ts.map +1 -1
- package/dist/execution/event-bus.d.ts +44 -0
- package/dist/execution/event-bus.d.ts.map +1 -0
- package/dist/execution/event-bus.js +76 -0
- package/dist/execution/failure-classifier.d.ts +11 -0
- package/dist/execution/failure-classifier.d.ts.map +1 -0
- package/dist/execution/failure-classifier.js +66 -0
- package/dist/execution/progress-detector.d.ts +3 -0
- package/dist/execution/progress-detector.d.ts.map +1 -0
- package/dist/execution/progress-detector.js +23 -0
- package/dist/execution/recovery-controller.d.ts +24 -0
- package/dist/execution/recovery-controller.d.ts.map +1 -0
- package/dist/execution/recovery-controller.js +114 -0
- package/dist/execution/recovery-messages.d.ts +24 -0
- package/dist/execution/recovery-messages.d.ts.map +1 -0
- package/dist/execution/recovery-messages.js +48 -0
- package/dist/execution/recovery-metrics.d.ts +16 -0
- package/dist/execution/recovery-metrics.d.ts.map +1 -0
- package/dist/execution/recovery-metrics.js +73 -0
- package/dist/execution/recovery-strategy-planner.d.ts +6 -0
- package/dist/execution/recovery-strategy-planner.d.ts.map +1 -0
- package/dist/execution/recovery-strategy-planner.js +24 -0
- package/dist/execution/run-trace-store.d.ts +29 -0
- package/dist/execution/run-trace-store.d.ts.map +1 -0
- package/dist/execution/run-trace-store.js +140 -0
- package/dist/execution/staged-verifier.d.ts +33 -0
- package/dist/execution/staged-verifier.d.ts.map +1 -0
- package/dist/execution/staged-verifier.js +39 -0
- package/dist/execution/types.d.ts +58 -0
- package/dist/execution/types.d.ts.map +1 -0
- package/dist/execution/types.js +1 -0
- package/dist/execution/verification-loop.d.ts +58 -0
- package/dist/execution/verification-loop.d.ts.map +1 -0
- package/dist/execution/verification-loop.js +195 -0
- package/dist/execution/verification-stages.d.ts +17 -0
- package/dist/execution/verification-stages.d.ts.map +1 -0
- package/dist/execution/verification-stages.js +102 -0
- package/dist/help-topics.d.ts.map +1 -1
- package/dist/help-topics.js +11 -0
- package/dist/index.js +0 -8
- package/dist/lsp/ts-service.d.ts +36 -0
- package/dist/lsp/ts-service.d.ts.map +1 -0
- package/dist/lsp/ts-service.js +291 -0
- package/dist/memory/lifecycle.d.ts +19 -0
- package/dist/memory/lifecycle.d.ts.map +1 -0
- package/dist/memory/lifecycle.js +53 -0
- package/dist/memory.d.ts +0 -16
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +0 -36
- package/dist/metrics/collector.d.ts +7 -0
- package/dist/metrics/collector.d.ts.map +1 -1
- package/dist/metrics/collector.js +60 -0
- package/dist/mission/manager.d.ts +1 -0
- package/dist/mission/manager.d.ts.map +1 -1
- package/dist/mission/manager.js +9 -0
- package/dist/mission/progress-notify.d.ts +39 -0
- package/dist/mission/progress-notify.d.ts.map +1 -0
- package/dist/mission/progress-notify.js +386 -0
- package/dist/pipeline/hooks.d.ts +1 -1
- package/dist/pipeline/hooks.d.ts.map +1 -1
- package/dist/pipeline/hooks.js +1 -0
- package/dist/pipeline/sections.d.ts +8 -4
- package/dist/pipeline/sections.d.ts.map +1 -1
- package/dist/pipeline/sections.js +70 -27
- package/dist/pipeline/verification.d.ts +1 -0
- package/dist/pipeline/verification.d.ts.map +1 -1
- package/dist/pipeline/verification.js +10 -7
- package/dist/providers/llm-client.d.ts +38 -0
- package/dist/providers/llm-client.d.ts.map +1 -0
- package/dist/providers/llm-client.js +105 -0
- package/dist/sdk.d.ts +1 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +1 -0
- package/dist/session/durable-session-supervisor.d.ts.map +1 -1
- package/dist/session/durable-session-supervisor.js +13 -6
- package/dist/session/session-persistence.d.ts +29 -0
- package/dist/session/session-persistence.d.ts.map +1 -0
- package/dist/session/session-persistence.js +45 -0
- package/dist/session/session-scheduler.d.ts +8 -1
- package/dist/session/session-scheduler.d.ts.map +1 -1
- package/dist/session/session-scheduler.js +33 -4
- package/dist/session-task-report.d.ts +1 -0
- package/dist/session-task-report.d.ts.map +1 -1
- package/dist/session-task-report.js +2 -1
- package/dist/shortcuts.d.ts.map +1 -1
- package/dist/shortcuts.js +1 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +10 -0
- package/dist/skills/security-scan.d.ts +15 -0
- package/dist/skills/security-scan.d.ts.map +1 -0
- package/dist/skills/security-scan.js +95 -0
- package/dist/skills/types.d.ts +2 -0
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/statusline.d.ts +3 -3
- package/dist/statusline.d.ts.map +1 -1
- package/dist/statusline.js +9 -17
- package/dist/token-usage.d.ts +27 -0
- package/dist/token-usage.d.ts.map +1 -0
- package/dist/token-usage.js +107 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +5 -3
- package/dist/tools/browser-act-session.d.ts +48 -0
- package/dist/tools/browser-act-session.d.ts.map +1 -0
- package/dist/tools/browser-act-session.js +168 -0
- package/dist/tools/browser-act.d.ts +14 -0
- package/dist/tools/browser-act.d.ts.map +1 -0
- package/dist/tools/browser-act.js +297 -0
- package/dist/tools/code-symbols.d.ts +35 -0
- package/dist/tools/code-symbols.d.ts.map +1 -0
- package/dist/tools/code-symbols.js +257 -0
- package/dist/tools/index.d.ts +4 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +22 -2
- package/dist/tools/lsp.d.ts +13 -0
- package/dist/tools/lsp.d.ts.map +1 -0
- package/dist/tools/lsp.js +136 -0
- package/dist/tools/patch.d.ts +5 -0
- package/dist/tools/patch.d.ts.map +1 -1
- package/dist/tools/patch.js +25 -4
- package/dist/tools/search.d.ts +7 -0
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +20 -3
- package/dist/tools/skill.d.ts +2 -0
- package/dist/tools/skill.d.ts.map +1 -1
- package/dist/tools/skill.js +47 -14
- package/dist/tools/subtask.d.ts +3 -1
- package/dist/tools/subtask.d.ts.map +1 -1
- package/dist/tools/subtask.js +151 -56
- package/dist/tui/shell.d.ts +12 -0
- package/dist/tui/shell.d.ts.map +1 -1
- package/dist/tui/shell.js +36 -3
- package/dist/tui/streaming-repl.d.ts +1 -0
- package/dist/tui/streaming-repl.d.ts.map +1 -1
- package/dist/tui/streaming-repl.js +27 -4
- package/dist/tui/streaming-tui.d.ts +10 -0
- package/dist/tui/streaming-tui.d.ts.map +1 -1
- package/dist/tui/streaming-tui.js +70 -12
- package/dist/types.d.ts +0 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/workflow-runtime.d.ts.map +1 -1
- package/dist/workflow-runtime.js +10 -2
- package/dist/workflow-types.d.ts +2 -0
- package/dist/workflow-types.d.ts.map +1 -1
- package/docs/install.md +29 -8
- package/docs/skills.md +56 -7
- package/docs/web-routing.md +83 -0
- package/package.json +18 -4
- package/scripts/dep-layers.mjs +275 -0
- package/scripts/eval-llm.mjs +27 -0
- package/scripts/eval-recovery.mjs +101 -0
- package/scripts/eval-tasks.mjs +20 -0
- package/scripts/validate-packaging.mjs +51 -0
- package/skills/examples/README.md +23 -0
- package/skills/examples/add-function/SKILL.md +31 -0
- package/skills/examples/fix-failing-test/SKILL.md +32 -0
- package/skills/examples/pr-summary/SKILL.md +34 -0
- package/skills/lifecycle-build/SKILL.md +22 -0
- package/skills/lifecycle-plan/SKILL.md +32 -0
- package/skills/lifecycle-review/SKILL.md +25 -0
- package/skills/lifecycle-ship/SKILL.md +22 -0
- package/skills/lifecycle-spec/SKILL.md +24 -0
- package/skills/lifecycle-test/SKILL.md +21 -0
- package/skills/opencli/SKILL.md +222 -0
- package/skills/qling.md +14 -3
package/dist/skills/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd"}
|
package/dist/statusline.d.ts
CHANGED
|
@@ -9,8 +9,9 @@ export interface StatusLineSnapshot {
|
|
|
9
9
|
goalStatus: string | null;
|
|
10
10
|
activeTasks: number;
|
|
11
11
|
tokens: number;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
promptTokens?: number;
|
|
13
|
+
completionTokens?: number;
|
|
14
|
+
tokenSource?: "provider" | "unknown";
|
|
14
15
|
costPer1kTokens?: number | null;
|
|
15
16
|
inputQueue?: StatusLineInputQueueSnapshot;
|
|
16
17
|
}
|
|
@@ -23,7 +24,6 @@ export interface LocalStatusLineSnapshotOptions {
|
|
|
23
24
|
workspaceDir?: string | null;
|
|
24
25
|
model?: string | null;
|
|
25
26
|
permissionMode?: string | null;
|
|
26
|
-
maxTokens?: number | null;
|
|
27
27
|
costPer1kTokens?: number | null;
|
|
28
28
|
}
|
|
29
29
|
export declare function resolveGitBranch(workspaceDir?: string): string | null;
|
package/dist/statusline.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGjE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,
|
|
1
|
+
{"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGjE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,4BAA4B,CAAC;CAC3C;AAED,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AA4BD,wBAAgB,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWrE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAa5E;AAiBD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEpE;AAqBD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CA4BrE;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,8BAA8B,GAAG,kBAAkB,CAe1G;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmDzG;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF"}
|
package/dist/statusline.js
CHANGED
|
@@ -80,15 +80,6 @@ function normalizePositiveNumber(value) {
|
|
|
80
80
|
export function parseStatusLineCostPer1k(raw) {
|
|
81
81
|
return normalizePositiveNumber(raw);
|
|
82
82
|
}
|
|
83
|
-
function formatContextUsage(tokens, maxTokens) {
|
|
84
|
-
const used = Math.max(0, Math.floor(Number(tokens ?? 0)));
|
|
85
|
-
const max = normalizePositiveNumber(maxTokens);
|
|
86
|
-
if (!max)
|
|
87
|
-
return `${used.toLocaleString()}/-`;
|
|
88
|
-
const roundedMax = Math.floor(max);
|
|
89
|
-
const pct = Math.round((used / roundedMax) * 100);
|
|
90
|
-
return `${used.toLocaleString()}/${roundedMax.toLocaleString()}(${pct}%)`;
|
|
91
|
-
}
|
|
92
83
|
function formatCostEstimate(tokens, costPer1kTokens) {
|
|
93
84
|
const costPer1k = normalizePositiveNumber(costPer1kTokens);
|
|
94
85
|
if (!costPer1k)
|
|
@@ -98,11 +89,7 @@ function formatCostEstimate(tokens, costPer1kTokens) {
|
|
|
98
89
|
return `≈$${estimate.toFixed(4)}`;
|
|
99
90
|
}
|
|
100
91
|
function normalizeTokenSource(value) {
|
|
101
|
-
return value === "provider"
|
|
102
|
-
}
|
|
103
|
-
function resolveTokenBudgetMax(agentLoop) {
|
|
104
|
-
const value = agentLoop.getTokenBudget?.()?.maxTokens ?? agentLoop.tokenBudget?.maxTokens;
|
|
105
|
-
return normalizePositiveNumber(value);
|
|
92
|
+
return value === "provider" ? "provider" : "unknown";
|
|
106
93
|
}
|
|
107
94
|
function formatSessionMode(mode) {
|
|
108
95
|
const m = String(mode ?? "").trim().toLowerCase();
|
|
@@ -119,6 +106,8 @@ export function formatStatusLine(snapshot) {
|
|
|
119
106
|
const permission = formatPermissionMode(snapshot.permissionMode);
|
|
120
107
|
const sessionMode = formatSessionMode(snapshot.sessionMode);
|
|
121
108
|
const cost = formatCostEstimate(snapshot.tokens, snapshot.costPer1kTokens);
|
|
109
|
+
const prompt = Math.max(0, Math.floor(Number(snapshot.promptTokens ?? 0)));
|
|
110
|
+
const completion = Math.max(0, Math.floor(Number(snapshot.completionTokens ?? 0)));
|
|
122
111
|
const parts = [
|
|
123
112
|
`模型=${snapshot.model || "未知"}`,
|
|
124
113
|
`模式=${sessionMode}`,
|
|
@@ -128,8 +117,9 @@ export function formatStatusLine(snapshot) {
|
|
|
128
117
|
`目标=${goal}`,
|
|
129
118
|
`任务=${snapshot.activeTasks}`,
|
|
130
119
|
`令牌=${Number(snapshot.tokens ?? 0).toLocaleString()}`,
|
|
120
|
+
`in=${prompt.toLocaleString()}`,
|
|
121
|
+
`out=${completion.toLocaleString()}`,
|
|
131
122
|
`来源=${normalizeTokenSource(snapshot.tokenSource)}`,
|
|
132
|
-
`上下文=${formatContextUsage(snapshot.tokens, snapshot.maxTokens)}`,
|
|
133
123
|
cost === "-" ? "成本=-" : `成本${cost}`,
|
|
134
124
|
];
|
|
135
125
|
const queue = formatInputQueueStatus(snapshot.inputQueue);
|
|
@@ -148,8 +138,9 @@ export function collectLocalStatusLineSnapshot(options) {
|
|
|
148
138
|
goalStatus: null,
|
|
149
139
|
activeTasks: 0,
|
|
150
140
|
tokens: 0,
|
|
141
|
+
promptTokens: 0,
|
|
142
|
+
completionTokens: 0,
|
|
151
143
|
tokenSource: "unknown",
|
|
152
|
-
maxTokens: normalizePositiveNumber(options.maxTokens),
|
|
153
144
|
costPer1kTokens: parseStatusLineCostPer1k(options.costPer1kTokens),
|
|
154
145
|
};
|
|
155
146
|
}
|
|
@@ -196,8 +187,9 @@ export async function collectStatusLineSnapshot(context) {
|
|
|
196
187
|
goalStatus: goal?.status ?? null,
|
|
197
188
|
activeTasks,
|
|
198
189
|
tokens: Number(stats.tokens ?? 0),
|
|
190
|
+
promptTokens: Number(stats.promptTokens ?? 0),
|
|
191
|
+
completionTokens: Number(stats.completionTokens ?? 0),
|
|
199
192
|
tokenSource: normalizeTokenSource(stats.tokenSource),
|
|
200
|
-
maxTokens: resolveTokenBudgetMax(agentLoop),
|
|
201
193
|
costPer1kTokens: parseStatusLineCostPer1k(process.env.QLING_STATUSLINE_COST_PER_1K_TOKENS),
|
|
202
194
|
inputQueue,
|
|
203
195
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type TokenUsageSource = "provider" | "unknown";
|
|
2
|
+
export interface ChatUsage {
|
|
3
|
+
promptTokens?: number;
|
|
4
|
+
completionTokens?: number;
|
|
5
|
+
totalTokens: number;
|
|
6
|
+
raw?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface ResolvedTokenUsage {
|
|
9
|
+
tokens: number;
|
|
10
|
+
promptTokens: number;
|
|
11
|
+
completionTokens: number;
|
|
12
|
+
source: TokenUsageSource;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 从 chat/completions 或 Ollama 等响应中提取官方 usage。
|
|
16
|
+
* 支持嵌套 `usage` 与顶层计数字段。
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractProviderUsage(raw: unknown): ChatUsage | undefined;
|
|
19
|
+
/** 将本轮官方 usage 解析为可累加的会话增量。 */
|
|
20
|
+
export declare function resolveRoundTokenUsage(usage: ChatUsage | undefined): ResolvedTokenUsage;
|
|
21
|
+
export declare function formatProviderTokenLine(options: {
|
|
22
|
+
tokens: number;
|
|
23
|
+
promptTokens?: number;
|
|
24
|
+
completionTokens?: number;
|
|
25
|
+
source?: TokenUsageSource;
|
|
26
|
+
}): string;
|
|
27
|
+
//# sourceMappingURL=token-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.d.ts","sourceRoot":"","sources":["../src/token-usage.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAoBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAqDxE;AAED,+BAA+B;AAC/B,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,kBAAkB,CAevF;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,GAAG,MAAM,CAaT"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// 轻灵 — 模型官方 Token Usage 解析
|
|
3
|
+
// 仅信任 provider 返回字段,不做字符启发式账单估算。
|
|
4
|
+
// ============================================================
|
|
5
|
+
function positiveInt(value) {
|
|
6
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
7
|
+
if (!Number.isFinite(n) || n < 0)
|
|
8
|
+
return undefined;
|
|
9
|
+
const floored = Math.floor(n);
|
|
10
|
+
return floored >= 0 ? floored : undefined;
|
|
11
|
+
}
|
|
12
|
+
function firstPositive(obj, keys) {
|
|
13
|
+
for (const key of keys) {
|
|
14
|
+
if (!(key in obj))
|
|
15
|
+
continue;
|
|
16
|
+
const n = positiveInt(obj[key]);
|
|
17
|
+
if (n !== undefined && n > 0)
|
|
18
|
+
return n;
|
|
19
|
+
// 允许 0(空 completion 等)
|
|
20
|
+
if (n === 0)
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 从 chat/completions 或 Ollama 等响应中提取官方 usage。
|
|
27
|
+
* 支持嵌套 `usage` 与顶层计数字段。
|
|
28
|
+
*/
|
|
29
|
+
export function extractProviderUsage(raw) {
|
|
30
|
+
if (!raw || typeof raw !== "object")
|
|
31
|
+
return undefined;
|
|
32
|
+
const root = raw;
|
|
33
|
+
const nested = root.usage && typeof root.usage === "object"
|
|
34
|
+
? root.usage
|
|
35
|
+
: root;
|
|
36
|
+
const promptTokens = firstPositive(nested, [
|
|
37
|
+
"prompt_tokens",
|
|
38
|
+
"promptTokens",
|
|
39
|
+
"input_tokens",
|
|
40
|
+
"inputTokens",
|
|
41
|
+
"prompt_eval_count",
|
|
42
|
+
"promptEvalCount",
|
|
43
|
+
]);
|
|
44
|
+
const completionTokens = firstPositive(nested, [
|
|
45
|
+
"completion_tokens",
|
|
46
|
+
"completionTokens",
|
|
47
|
+
"output_tokens",
|
|
48
|
+
"outputTokens",
|
|
49
|
+
"eval_count",
|
|
50
|
+
"evalCount",
|
|
51
|
+
]);
|
|
52
|
+
let totalTokens = firstPositive(nested, [
|
|
53
|
+
"total_tokens",
|
|
54
|
+
"totalTokens",
|
|
55
|
+
"total",
|
|
56
|
+
]);
|
|
57
|
+
if (totalTokens === undefined) {
|
|
58
|
+
if (promptTokens !== undefined || completionTokens !== undefined) {
|
|
59
|
+
totalTokens = (promptTokens ?? 0) + (completionTokens ?? 0);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (totalTokens === undefined || totalTokens <= 0) {
|
|
63
|
+
// 若 total 为 0 但有明确 prompt/completion 0 之和,仍视为无有效用量
|
|
64
|
+
if (totalTokens === 0 && (promptTokens ?? 0) + (completionTokens ?? 0) === 0) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
if (totalTokens === undefined)
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
if (totalTokens <= 0)
|
|
71
|
+
return undefined;
|
|
72
|
+
return {
|
|
73
|
+
promptTokens,
|
|
74
|
+
completionTokens,
|
|
75
|
+
totalTokens,
|
|
76
|
+
raw: nested,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** 将本轮官方 usage 解析为可累加的会话增量。 */
|
|
80
|
+
export function resolveRoundTokenUsage(usage) {
|
|
81
|
+
if (usage && Number.isFinite(usage.totalTokens) && usage.totalTokens > 0) {
|
|
82
|
+
return {
|
|
83
|
+
tokens: Math.floor(usage.totalTokens),
|
|
84
|
+
promptTokens: Math.max(0, Math.floor(usage.promptTokens ?? 0)),
|
|
85
|
+
completionTokens: Math.max(0, Math.floor(usage.completionTokens ?? 0)),
|
|
86
|
+
source: "provider",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
tokens: 0,
|
|
91
|
+
promptTokens: 0,
|
|
92
|
+
completionTokens: 0,
|
|
93
|
+
source: "unknown",
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function formatProviderTokenLine(options) {
|
|
97
|
+
const tokens = Math.max(0, Math.floor(options.tokens ?? 0));
|
|
98
|
+
const prompt = options.promptTokens;
|
|
99
|
+
const completion = options.completionTokens;
|
|
100
|
+
const source = options.source ?? "unknown";
|
|
101
|
+
if (typeof prompt === "number" &&
|
|
102
|
+
typeof completion === "number" &&
|
|
103
|
+
(prompt > 0 || completion > 0)) {
|
|
104
|
+
return `${tokens.toLocaleString()} (in ${prompt.toLocaleString()} + out ${completion.toLocaleString()}, ${source})`;
|
|
105
|
+
}
|
|
106
|
+
return `${tokens.toLocaleString()} (${source})`;
|
|
107
|
+
}
|
package/dist/tools/bash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzD,eAAO,MAAM,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzD,eAAO,MAAM,QAAQ,EAAE,cAiGtB,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,GAAG,OAAO,CAAC,UAAU,CAAC,CAyJtB"}
|
package/dist/tools/bash.js
CHANGED
|
@@ -12,7 +12,7 @@ const MAX_COMMAND_LENGTH = 5000;
|
|
|
12
12
|
const MAX_OUTPUT_BYTES = 1024 * 1024; // 1MB per stream
|
|
13
13
|
export const bashTool = {
|
|
14
14
|
name: "bash",
|
|
15
|
-
description: "Execute shell commands
|
|
15
|
+
description: "Execute shell commands (git, npm, opencli, file ops). For Douyin/Xiaohongshu/Weibo/etc. run opencli after skill name=opencli; prefer opencli … -f json. Not for raw fetch of anti-bot pages.",
|
|
16
16
|
longDescription: `执行 shell 命令的万能工具。**Linux**: 通过 /bin/sh 执行。**Windows**: 通过 cmd.exe 执行(而非 PowerShell)。
|
|
17
17
|
**重要 - Windows 用户**:Windows 上请使用标准的 cmd.exe 命令(dir, type, copy, del 等),不要使用 PowerShell 独有语法(Invoke-WebRequest 等)。cmd.exe 不支持 PowerShell cmdlet。
|
|
18
18
|
**Linux 用户**:通过 /bin/sh 执行标准 POSIX 命令。
|
|
@@ -20,15 +20,17 @@ export const bashTool = {
|
|
|
20
20
|
**使用场景**:
|
|
21
21
|
- git 操作(git add, git commit, git push)
|
|
22
22
|
- npm/node 命令(npm install, node scripts)
|
|
23
|
+
- **opencli**(本机已安装时):opencli list / opencli douyin search … -f json(先 skill name="opencli")
|
|
23
24
|
- 文件操作(ls, cp, mv, mkdir)
|
|
24
25
|
- 进程管理(ps, kill, pgrep)
|
|
25
|
-
- 网络工具(curl, wget, ping
|
|
26
|
+
- 网络工具(curl, wget, ping)— 强反爬社交站不要用 curl 硬抓
|
|
26
27
|
- 编译构建(make, gcc, cargo)
|
|
27
28
|
|
|
28
29
|
**注意事项**:
|
|
29
30
|
- rm -rf 等危险操作会被 Hook 拦截并要求确认
|
|
30
31
|
- Windows 下需要通过 cmd.exe /c 执行
|
|
31
|
-
- 长时间运行的命令建议设置 timeout
|
|
32
|
+
- 长时间运行的命令建议设置 timeout
|
|
33
|
+
- opencli 写操作(delete/publish)须用户确认`,
|
|
32
34
|
parameters: {
|
|
33
35
|
type: "object",
|
|
34
36
|
properties: {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type Browser, type BrowserContext, type Page } from "playwright";
|
|
2
|
+
export interface BrowserSessionHandle {
|
|
3
|
+
id: string;
|
|
4
|
+
browser: Browser;
|
|
5
|
+
context: BrowserContext;
|
|
6
|
+
page: Page;
|
|
7
|
+
lastUrl: string;
|
|
8
|
+
createdAt: number;
|
|
9
|
+
lastUsedAt: number;
|
|
10
|
+
requestGuardInstalled: boolean;
|
|
11
|
+
}
|
|
12
|
+
export type BrowserRequestGuard = (url: string) => Promise<boolean>;
|
|
13
|
+
export interface BrowserSessionPoolOptions {
|
|
14
|
+
/** 最大并发会话数 */
|
|
15
|
+
maxSessions?: number;
|
|
16
|
+
/** 空闲超时 ms,超过则自动关闭 */
|
|
17
|
+
idleTtlMs?: number;
|
|
18
|
+
/** 注入的 launch 工厂(测试用) */
|
|
19
|
+
launchBrowser?: () => Promise<Browser>;
|
|
20
|
+
}
|
|
21
|
+
export declare class BrowserSessionPool {
|
|
22
|
+
private sessions;
|
|
23
|
+
private maxSessions;
|
|
24
|
+
private idleTtlMs;
|
|
25
|
+
private launchBrowser;
|
|
26
|
+
constructor(options?: BrowserSessionPoolOptions);
|
|
27
|
+
list(): Array<{
|
|
28
|
+
id: string;
|
|
29
|
+
lastUrl: string;
|
|
30
|
+
ageMs: number;
|
|
31
|
+
idleMs: number;
|
|
32
|
+
}>;
|
|
33
|
+
has(id: string): boolean;
|
|
34
|
+
get(id: string): BrowserSessionHandle | undefined;
|
|
35
|
+
/** 关闭并移除空闲超时会话 */
|
|
36
|
+
sweepIdle(now?: number): Promise<string[]>;
|
|
37
|
+
open(id: string, requestGuard?: BrowserRequestGuard): Promise<BrowserSessionHandle>;
|
|
38
|
+
private installRequestGuard;
|
|
39
|
+
touch(id: string, lastUrl?: string): void;
|
|
40
|
+
close(id: string): Promise<boolean>;
|
|
41
|
+
closeAll(): Promise<void>;
|
|
42
|
+
size(): number;
|
|
43
|
+
}
|
|
44
|
+
export declare function getBrowserSessionPool(): BrowserSessionPool;
|
|
45
|
+
/** 测试用:替换 / 清空默认池 */
|
|
46
|
+
export declare function resetBrowserSessionPool(pool?: BrowserSessionPool | null): void;
|
|
47
|
+
export declare function normalizeSessionId(raw: unknown): string;
|
|
48
|
+
//# sourceMappingURL=browser-act-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-act-session.d.ts","sourceRoot":"","sources":["../../src/tools/browser-act-session.ts"],"names":[],"mappings":"AAIA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpE,MAAM,WAAW,yBAAyB;IACxC,cAAc;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACxC;AAiBD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAyB;gBAElC,OAAO,GAAE,yBAA8B;IAWnD,IAAI,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAU7E,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAIjD,kBAAkB;IACZ,SAAS,CAAC,GAAG,SAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAY9C,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAiD3E,mBAAmB;IAgBjC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAOnC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQnC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B,IAAI,IAAI,MAAM;CAGf;AAKD,wBAAgB,qBAAqB,IAAI,kBAAkB,CAG1D;AAED,qBAAqB;AACrB,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAK9E;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAKvD"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// browser_act 跨步会话:进程内 Playwright page 保活
|
|
3
|
+
// ============================================================
|
|
4
|
+
import { chromium } from "playwright";
|
|
5
|
+
const DEFAULT_MAX = 3;
|
|
6
|
+
const DEFAULT_IDLE_TTL_MS = 10 * 60 * 1000;
|
|
7
|
+
function resolveMaxSessions(env = process.env) {
|
|
8
|
+
const n = Number(env.QLING_BROWSER_ACT_MAX_SESSIONS ?? DEFAULT_MAX);
|
|
9
|
+
if (!Number.isFinite(n) || n < 1)
|
|
10
|
+
return DEFAULT_MAX;
|
|
11
|
+
return Math.min(8, Math.floor(n));
|
|
12
|
+
}
|
|
13
|
+
function resolveIdleTtlMs(env = process.env) {
|
|
14
|
+
const n = Number(env.QLING_BROWSER_ACT_IDLE_TTL_MS ?? DEFAULT_IDLE_TTL_MS);
|
|
15
|
+
if (!Number.isFinite(n) || n < 0)
|
|
16
|
+
return DEFAULT_IDLE_TTL_MS;
|
|
17
|
+
return Math.floor(n);
|
|
18
|
+
}
|
|
19
|
+
export class BrowserSessionPool {
|
|
20
|
+
sessions = new Map();
|
|
21
|
+
maxSessions;
|
|
22
|
+
idleTtlMs;
|
|
23
|
+
launchBrowser;
|
|
24
|
+
constructor(options = {}) {
|
|
25
|
+
this.maxSessions = options.maxSessions ?? resolveMaxSessions();
|
|
26
|
+
this.idleTtlMs = options.idleTtlMs ?? resolveIdleTtlMs();
|
|
27
|
+
this.launchBrowser =
|
|
28
|
+
options.launchBrowser ??
|
|
29
|
+
(() => chromium.launch({
|
|
30
|
+
headless: true,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
list() {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
return Array.from(this.sessions.values()).map((s) => ({
|
|
36
|
+
id: s.id,
|
|
37
|
+
lastUrl: s.lastUrl,
|
|
38
|
+
ageMs: now - s.createdAt,
|
|
39
|
+
idleMs: now - s.lastUsedAt,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
has(id) {
|
|
43
|
+
return this.sessions.has(id);
|
|
44
|
+
}
|
|
45
|
+
get(id) {
|
|
46
|
+
return this.sessions.get(id);
|
|
47
|
+
}
|
|
48
|
+
/** 关闭并移除空闲超时会话 */
|
|
49
|
+
async sweepIdle(now = Date.now()) {
|
|
50
|
+
if (this.idleTtlMs <= 0)
|
|
51
|
+
return [];
|
|
52
|
+
const closed = [];
|
|
53
|
+
for (const [id, s] of this.sessions) {
|
|
54
|
+
if (now - s.lastUsedAt >= this.idleTtlMs) {
|
|
55
|
+
await this.close(id);
|
|
56
|
+
closed.push(id);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return closed;
|
|
60
|
+
}
|
|
61
|
+
async open(id, requestGuard) {
|
|
62
|
+
await this.sweepIdle();
|
|
63
|
+
const existing = this.sessions.get(id);
|
|
64
|
+
if (existing) {
|
|
65
|
+
if (requestGuard && !existing.requestGuardInstalled) {
|
|
66
|
+
await this.installRequestGuard(existing.context, requestGuard);
|
|
67
|
+
existing.requestGuardInstalled = true;
|
|
68
|
+
}
|
|
69
|
+
existing.lastUsedAt = Date.now();
|
|
70
|
+
return existing;
|
|
71
|
+
}
|
|
72
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
73
|
+
// 驱逐最久未用
|
|
74
|
+
let oldestId = null;
|
|
75
|
+
let oldest = Infinity;
|
|
76
|
+
for (const [sid, s] of this.sessions) {
|
|
77
|
+
if (s.lastUsedAt < oldest) {
|
|
78
|
+
oldest = s.lastUsedAt;
|
|
79
|
+
oldestId = sid;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (oldestId)
|
|
83
|
+
await this.close(oldestId);
|
|
84
|
+
}
|
|
85
|
+
const browser = await this.launchBrowser();
|
|
86
|
+
const context = await browser.newContext({
|
|
87
|
+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
88
|
+
});
|
|
89
|
+
if (requestGuard) {
|
|
90
|
+
await this.installRequestGuard(context, requestGuard);
|
|
91
|
+
}
|
|
92
|
+
const page = await context.newPage();
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
const handle = {
|
|
95
|
+
id,
|
|
96
|
+
browser,
|
|
97
|
+
context,
|
|
98
|
+
page,
|
|
99
|
+
lastUrl: "",
|
|
100
|
+
createdAt: now,
|
|
101
|
+
lastUsedAt: now,
|
|
102
|
+
requestGuardInstalled: Boolean(requestGuard),
|
|
103
|
+
};
|
|
104
|
+
this.sessions.set(id, handle);
|
|
105
|
+
return handle;
|
|
106
|
+
}
|
|
107
|
+
async installRequestGuard(context, requestGuard) {
|
|
108
|
+
await context.route("**/*", async (route) => {
|
|
109
|
+
let allowed = false;
|
|
110
|
+
try {
|
|
111
|
+
allowed = await requestGuard(route.request().url());
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
allowed = false;
|
|
115
|
+
}
|
|
116
|
+
if (allowed)
|
|
117
|
+
await route.continue();
|
|
118
|
+
else
|
|
119
|
+
await route.abort("blockedbyclient");
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
touch(id, lastUrl) {
|
|
123
|
+
const s = this.sessions.get(id);
|
|
124
|
+
if (!s)
|
|
125
|
+
return;
|
|
126
|
+
s.lastUsedAt = Date.now();
|
|
127
|
+
if (lastUrl !== undefined)
|
|
128
|
+
s.lastUrl = lastUrl;
|
|
129
|
+
}
|
|
130
|
+
async close(id) {
|
|
131
|
+
const s = this.sessions.get(id);
|
|
132
|
+
if (!s)
|
|
133
|
+
return false;
|
|
134
|
+
this.sessions.delete(id);
|
|
135
|
+
await s.browser.close().catch(() => undefined);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
async closeAll() {
|
|
139
|
+
const ids = Array.from(this.sessions.keys());
|
|
140
|
+
for (const id of ids) {
|
|
141
|
+
await this.close(id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
size() {
|
|
145
|
+
return this.sessions.size;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** 进程内默认池(browser_act 共用) */
|
|
149
|
+
let defaultPool = null;
|
|
150
|
+
export function getBrowserSessionPool() {
|
|
151
|
+
if (!defaultPool)
|
|
152
|
+
defaultPool = new BrowserSessionPool();
|
|
153
|
+
return defaultPool;
|
|
154
|
+
}
|
|
155
|
+
/** 测试用:替换 / 清空默认池 */
|
|
156
|
+
export function resetBrowserSessionPool(pool) {
|
|
157
|
+
if (defaultPool) {
|
|
158
|
+
void defaultPool.closeAll();
|
|
159
|
+
}
|
|
160
|
+
defaultPool = pool === undefined ? null : pool;
|
|
161
|
+
}
|
|
162
|
+
export function normalizeSessionId(raw) {
|
|
163
|
+
const s = String(raw ?? "default").trim();
|
|
164
|
+
if (!s)
|
|
165
|
+
return "default";
|
|
166
|
+
// 防止路径穿越式 id
|
|
167
|
+
return s.replace(/[^\w.-]+/g, "_").slice(0, 64) || "default";
|
|
168
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ToolDefinition, ToolResult } from "../types.js";
|
|
2
|
+
export type BrowserActAction = "open" | "close" | "status" | "goto" | "click" | "type" | "wait_for" | "extract" | "press";
|
|
3
|
+
export declare function isBrowserActEnabled(env?: NodeJS.ProcessEnv | Record<string, string | undefined>): boolean;
|
|
4
|
+
export declare const browserActTool: ToolDefinition;
|
|
5
|
+
export declare function runBrowserAct(args: {
|
|
6
|
+
action?: string;
|
|
7
|
+
session?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
selector?: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
key?: string;
|
|
12
|
+
timeout_ms?: number;
|
|
13
|
+
}): Promise<ToolResult>;
|
|
14
|
+
//# sourceMappingURL=browser-act.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-act.d.ts","sourceRoot":"","sources":["../../src/tools/browser-act.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9D,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,OAAO,GACP,QAAQ,GACR,MAAM,GACN,OAAO,GACP,MAAM,GACN,UAAU,GACV,SAAS,GACT,OAAO,CAAC;AAIZ,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACxE,OAAO,CAGT;AAED,eAAO,MAAM,cAAc,EAAE,cA+C5B,CAAC;AAwDF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,UAAU,CAAC,CAsNtB"}
|