@adhdev/daemon-core 0.9.82-rc.353 → 0.9.82-rc.354
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/commands/handler.d.ts +15 -0
- package/dist/index.js +136 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +136 -22
- package/dist/index.mjs.map +1 -1
- package/dist/providers/acp-provider-instance.d.ts +3 -0
- package/dist/providers/cli-provider-instance.d.ts +12 -0
- package/dist/providers/manual-attendance.d.ts +63 -0
- package/dist/providers/provider-instance.d.ts +8 -0
- package/package.json +2 -2
- package/src/commands/cli-manager.ts +20 -2
- package/src/commands/handler.ts +32 -0
- package/src/git/git-diff.ts +31 -14
- package/src/providers/acp-provider-instance.ts +18 -1
- package/src/providers/cli-provider-instance.ts +54 -3
- package/src/providers/manual-attendance.ts +85 -0
- package/src/providers/provider-instance.ts +9 -0
package/dist/index.mjs
CHANGED
|
@@ -311,10 +311,10 @@ function readInjected(value) {
|
|
|
311
311
|
}
|
|
312
312
|
function getDaemonBuildInfo() {
|
|
313
313
|
if (cached) return cached;
|
|
314
|
-
const commit = readInjected(true ? "
|
|
315
|
-
const commitShort = readInjected(true ? "
|
|
316
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
317
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
314
|
+
const commit = readInjected(true ? "5d100a177f412ae29a58048f0a211c3928b06910" : void 0) ?? "unknown";
|
|
315
|
+
const commitShort = readInjected(true ? "5d100a17" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
316
|
+
const version = readInjected(true ? "0.9.82-rc.354" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
317
|
+
const builtAt = readInjected(true ? "2026-06-22T11:32:05.389Z" : void 0);
|
|
318
318
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
319
319
|
return cached;
|
|
320
320
|
}
|
|
@@ -1067,6 +1067,9 @@ __export(git_diff_exports, {
|
|
|
1067
1067
|
});
|
|
1068
1068
|
import { readFile, realpath as realpath2 } from "fs/promises";
|
|
1069
1069
|
import * as path2 from "path";
|
|
1070
|
+
function withCollectionTimeout(options) {
|
|
1071
|
+
return options.timeoutMs === void 0 ? { ...options, timeoutMs: GIT_STATUS_TIMEOUT_MS } : options;
|
|
1072
|
+
}
|
|
1070
1073
|
function validateBaseRef(ref) {
|
|
1071
1074
|
const trimmed = ref.trim();
|
|
1072
1075
|
if (!trimmed || trimmed.startsWith("-") || trimmed.includes("..") || !/^[A-Za-z0-9][A-Za-z0-9._/@-]*$/.test(trimmed)) {
|
|
@@ -1076,14 +1079,15 @@ function validateBaseRef(ref) {
|
|
|
1076
1079
|
}
|
|
1077
1080
|
async function getGitDiffSummary(workspace, options = {}) {
|
|
1078
1081
|
const lastCheckedAt = Date.now();
|
|
1082
|
+
const effectiveOptions = withCollectionTimeout(options);
|
|
1079
1083
|
try {
|
|
1080
|
-
const repo = await resolveGitRepository(workspace,
|
|
1084
|
+
const repo = await resolveGitRepository(workspace, effectiveOptions);
|
|
1081
1085
|
const repoRoot = repo.repoRoot;
|
|
1082
1086
|
if (options.baseRef) {
|
|
1083
1087
|
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
1084
1088
|
const [nameStatus, numstat] = await Promise.all([
|
|
1085
|
-
runGit(repo, ["diff", "--no-ext-diff", "--name-status", range, "--"], { ...
|
|
1086
|
-
runGit(repo, ["diff", "--no-ext-diff", "--numstat", range, "--"], { ...
|
|
1089
|
+
runGit(repo, ["diff", "--no-ext-diff", "--name-status", range, "--"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1090
|
+
runGit(repo, ["diff", "--no-ext-diff", "--numstat", range, "--"], { ...effectiveOptions, cwd: repoRoot })
|
|
1087
1091
|
]);
|
|
1088
1092
|
const outputBytes2 = byteLength(nameStatus.stdout + numstat.stdout);
|
|
1089
1093
|
const changes2 = combineDiffEntries(nameStatus.stdout, numstat.stdout, false);
|
|
@@ -1102,11 +1106,11 @@ async function getGitDiffSummary(workspace, options = {}) {
|
|
|
1102
1106
|
};
|
|
1103
1107
|
}
|
|
1104
1108
|
const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
|
|
1105
|
-
runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...
|
|
1106
|
-
runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...
|
|
1107
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...
|
|
1108
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...
|
|
1109
|
-
runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...
|
|
1109
|
+
runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1110
|
+
runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1111
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1112
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1113
|
+
runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...effectiveOptions, cwd: repoRoot })
|
|
1110
1114
|
]);
|
|
1111
1115
|
const outputBytes = byteLength(
|
|
1112
1116
|
unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
|
|
@@ -1148,13 +1152,14 @@ async function getGitDiffSummary(workspace, options = {}) {
|
|
|
1148
1152
|
}
|
|
1149
1153
|
async function getGitFileDiff(workspace, filePath, options = {}) {
|
|
1150
1154
|
const lastCheckedAt = Date.now();
|
|
1151
|
-
const
|
|
1155
|
+
const effectiveOptions = withCollectionTimeout(options);
|
|
1156
|
+
const repo = await resolveGitRepository(workspace, effectiveOptions);
|
|
1152
1157
|
const repoRoot = repo.repoRoot;
|
|
1153
1158
|
const selected = await resolveRepoFilePath(repoRoot, filePath);
|
|
1154
1159
|
const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
|
|
1155
1160
|
if (options.baseRef) {
|
|
1156
1161
|
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
1157
|
-
const result = await runGit(repo, ["diff", "--no-ext-diff", range, "--", selected.relativePath], { ...
|
|
1162
|
+
const result = await runGit(repo, ["diff", "--no-ext-diff", range, "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot });
|
|
1158
1163
|
const bounded2 = truncateText(result.stdout, maxBytes);
|
|
1159
1164
|
return {
|
|
1160
1165
|
workspace: repo.workspace,
|
|
@@ -1167,13 +1172,13 @@ async function getGitFileDiff(workspace, filePath, options = {}) {
|
|
|
1167
1172
|
};
|
|
1168
1173
|
}
|
|
1169
1174
|
const [unstaged, staged] = await Promise.all([
|
|
1170
|
-
runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...
|
|
1171
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...
|
|
1175
|
+
runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot }),
|
|
1176
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot })
|
|
1172
1177
|
]);
|
|
1173
1178
|
let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
|
|
1174
1179
|
if (!diff) {
|
|
1175
1180
|
const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
|
|
1176
|
-
...
|
|
1181
|
+
...effectiveOptions,
|
|
1177
1182
|
cwd: repoRoot
|
|
1178
1183
|
});
|
|
1179
1184
|
const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
|
|
@@ -27072,6 +27077,42 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
27072
27077
|
return fn() || null;
|
|
27073
27078
|
}
|
|
27074
27079
|
|
|
27080
|
+
// src/providers/manual-attendance.ts
|
|
27081
|
+
var AUTO_APPROVE_MANUAL_ATTENDANCE_SUPPRESS_MS = 6e4;
|
|
27082
|
+
var ManualAttendanceTracker = class {
|
|
27083
|
+
constructor(suppressMs = AUTO_APPROVE_MANUAL_ATTENDANCE_SUPPRESS_MS) {
|
|
27084
|
+
this.suppressMs = suppressMs;
|
|
27085
|
+
}
|
|
27086
|
+
lastInteractionAt = 0;
|
|
27087
|
+
/** Record that a human just drove this session by hand. */
|
|
27088
|
+
note(now = Date.now()) {
|
|
27089
|
+
this.lastInteractionAt = now;
|
|
27090
|
+
}
|
|
27091
|
+
/** True while a manual interaction is recent enough to suppress auto-approve. */
|
|
27092
|
+
isAttended(now = Date.now()) {
|
|
27093
|
+
return this.lastInteractionAt > 0 && now - this.lastInteractionAt < this.suppressMs;
|
|
27094
|
+
}
|
|
27095
|
+
/**
|
|
27096
|
+
* Milliseconds remaining in the current suppression window, or 0 when not
|
|
27097
|
+
* attended. Used to re-arm a re-check timer so auto-approve fires the moment
|
|
27098
|
+
* the window lapses even if the PTY/agent has since gone silent.
|
|
27099
|
+
*/
|
|
27100
|
+
remainingMs(now = Date.now()) {
|
|
27101
|
+
if (this.lastInteractionAt <= 0) return 0;
|
|
27102
|
+
return Math.max(0, this.suppressMs - (now - this.lastInteractionAt));
|
|
27103
|
+
}
|
|
27104
|
+
};
|
|
27105
|
+
var MANUAL_ATTENDANCE_COMMANDS = /* @__PURE__ */ new Set([
|
|
27106
|
+
"select_session",
|
|
27107
|
+
"open_panel",
|
|
27108
|
+
"invoke_provider_script",
|
|
27109
|
+
"set_mode",
|
|
27110
|
+
"change_model",
|
|
27111
|
+
"set_thought_level",
|
|
27112
|
+
"resolve_action",
|
|
27113
|
+
"pty_input"
|
|
27114
|
+
]);
|
|
27115
|
+
|
|
27075
27116
|
// src/commands/chat-commands.ts
|
|
27076
27117
|
init_contracts();
|
|
27077
27118
|
init_provider_input_support();
|
|
@@ -31411,11 +31452,38 @@ var DaemonCommandHandler = class {
|
|
|
31411
31452
|
setAgentStreamManager(manager) {
|
|
31412
31453
|
this._agentStream = manager;
|
|
31413
31454
|
}
|
|
31455
|
+
/**
|
|
31456
|
+
* When a command in the manual-attendance set arrives for a session this
|
|
31457
|
+
* daemon hosts, stamp the live instance so auto-approve holds while the user
|
|
31458
|
+
* drives the session by hand. Provider-common: the signal is the command
|
|
31459
|
+
* (foreground select_session / open_panel, controlbar invoke_provider_script
|
|
31460
|
+
* / set_mode / change_model / set_thought_level, manual resolve_action,
|
|
31461
|
+
* pty_input), never any CLI-specific modal text — so it works identically for
|
|
31462
|
+
* every CLI/ACP provider. send_chat is deliberately excluded because a
|
|
31463
|
+
* coordinator delegating a task to a worker also uses send_chat; counting it
|
|
31464
|
+
* would wrongly suppress the worker's delegated auto-approve. For a remote
|
|
31465
|
+
* mesh worker session the controlbar commands are forwarded to the owning
|
|
31466
|
+
* worker daemon, which runs this same hook there, so attendance is recorded
|
|
31467
|
+
* on the daemon that actually hosts the instance.
|
|
31468
|
+
*/
|
|
31469
|
+
noteManualAttendanceIfApplicable(cmd, args) {
|
|
31470
|
+
if (!MANUAL_ATTENDANCE_COMMANDS.has(cmd)) return;
|
|
31471
|
+
const sessionId = this._currentRoute.session?.sessionId || (typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "");
|
|
31472
|
+
if (!sessionId) return;
|
|
31473
|
+
const session = this._ctx.sessionRegistry?.get(sessionId);
|
|
31474
|
+
const instanceKey = session?.adapterKey || session?.instanceKey || sessionId;
|
|
31475
|
+
const instance = this._ctx.instanceManager?.getInstance(instanceKey);
|
|
31476
|
+
try {
|
|
31477
|
+
instance?.noteManualInteraction?.();
|
|
31478
|
+
} catch {
|
|
31479
|
+
}
|
|
31480
|
+
}
|
|
31414
31481
|
// ─── Command Dispatcher ──────────────────────────
|
|
31415
31482
|
async handle(cmd, args) {
|
|
31416
31483
|
this._currentRoute = this.resolveRoute(args);
|
|
31417
31484
|
const startedAt = Date.now();
|
|
31418
31485
|
this.logCommandStart(cmd, args);
|
|
31486
|
+
this.noteManualAttendanceIfApplicable(cmd, args);
|
|
31419
31487
|
let result;
|
|
31420
31488
|
if (isGitCommandName(cmd)) {
|
|
31421
31489
|
result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
|
|
@@ -35369,6 +35437,11 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35369
35437
|
// a settle gate was in progress. Drives AUTO_APPROVE_GATE_HYSTERESIS_MS so a
|
|
35370
35438
|
// brief generating flip does not immediately wipe the settle clock.
|
|
35371
35439
|
autoApproveInactiveSince = 0;
|
|
35440
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
35441
|
+
// this session from the dashboard, auto-approve holds so they can take manual
|
|
35442
|
+
// control. Background mesh workers are never attended → delegated auto-approve
|
|
35443
|
+
// is unaffected.
|
|
35444
|
+
manualAttendance = new ManualAttendanceTracker();
|
|
35372
35445
|
controlValues = {};
|
|
35373
35446
|
summaryMetadata = void 0;
|
|
35374
35447
|
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
@@ -35644,7 +35717,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35644
35717
|
}
|
|
35645
35718
|
getHotChatSessionState() {
|
|
35646
35719
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
35647
|
-
const autoApproveActive = adapterStatus.status
|
|
35720
|
+
const autoApproveActive = this.autoApproveEffectivelyActive(adapterStatus.status);
|
|
35648
35721
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
35649
35722
|
const visibleStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
35650
35723
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
@@ -35659,7 +35732,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35659
35732
|
}
|
|
35660
35733
|
getSessionModalState(sessionId) {
|
|
35661
35734
|
const adapterStatus = this.adapter.getStatus({ allowParse: true });
|
|
35662
|
-
const autoApproveActive = adapterStatus.status
|
|
35735
|
+
const autoApproveActive = this.autoApproveEffectivelyActive(adapterStatus.status);
|
|
35663
35736
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
35664
35737
|
const visibleStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
35665
35738
|
const dirName = workingDirBasename(this.workingDir);
|
|
@@ -35740,7 +35813,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35740
35813
|
} catch {
|
|
35741
35814
|
return null;
|
|
35742
35815
|
}
|
|
35743
|
-
if (adapterStatus.status === "waiting_approval" && !this.
|
|
35816
|
+
if (adapterStatus.status === "waiting_approval" && !this.autoApproveEffectivelyActive(adapterStatus.status)) {
|
|
35744
35817
|
return "waiting_approval";
|
|
35745
35818
|
}
|
|
35746
35819
|
return null;
|
|
@@ -36186,6 +36259,18 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36186
36259
|
this.lastApprovalEventFingerprint = "";
|
|
36187
36260
|
}
|
|
36188
36261
|
maybeAutoApproveStatus(adapterStatus, now = Date.now()) {
|
|
36262
|
+
if (adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove() && this.manualAttendance.isAttended(now)) {
|
|
36263
|
+
this.lastAutoApprovalSignature = "";
|
|
36264
|
+
this.pendingAutoApprovalSignature = "";
|
|
36265
|
+
this.pendingAutoApprovalSince = 0;
|
|
36266
|
+
this.autoApproveInactiveSince = 0;
|
|
36267
|
+
if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
|
|
36268
|
+
this.autoApproveSettleTimer = setTimeout(() => {
|
|
36269
|
+
this.autoApproveSettleTimer = null;
|
|
36270
|
+
this.recheckAutoApproveSettled();
|
|
36271
|
+
}, this.manualAttendance.remainingMs(now) + 20);
|
|
36272
|
+
return false;
|
|
36273
|
+
}
|
|
36189
36274
|
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
|
|
36190
36275
|
if (!autoApproveActive) {
|
|
36191
36276
|
this.lastAutoApprovalSignature = "";
|
|
@@ -36651,6 +36736,21 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36651
36736
|
}
|
|
36652
36737
|
return false;
|
|
36653
36738
|
}
|
|
36739
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
36740
|
+
noteManualInteraction(now = Date.now()) {
|
|
36741
|
+
this.manualAttendance.note(now);
|
|
36742
|
+
}
|
|
36743
|
+
/**
|
|
36744
|
+
* Whether auto-approve should be treated as active *right now* for display
|
|
36745
|
+
* and firing decisions: the configured intent AND the user is not currently
|
|
36746
|
+
* attending this session by hand. When a human is attending, auto-approve is
|
|
36747
|
+
* held so the modal stays visible and they can drive it via the controlbar.
|
|
36748
|
+
* Provider-agnostic — the attendance signal is the command set, never any
|
|
36749
|
+
* CLI-specific modal text.
|
|
36750
|
+
*/
|
|
36751
|
+
autoApproveEffectivelyActive(status, now = Date.now()) {
|
|
36752
|
+
return status === "waiting_approval" && this.shouldAutoApprove() && !this.manualAttendance.isAttended(now);
|
|
36753
|
+
}
|
|
36654
36754
|
recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
|
|
36655
36755
|
this.appendRuntimeSystemMessage(
|
|
36656
36756
|
formatAutoApprovalMessage(modalMessage, buttonLabel),
|
|
@@ -37601,7 +37701,7 @@ var AcpProviderInstance = class {
|
|
|
37601
37701
|
input: tc.rawInput ? typeof tc.rawInput === "string" ? tc.rawInput : JSON.stringify(tc.rawInput) : void 0
|
|
37602
37702
|
});
|
|
37603
37703
|
}
|
|
37604
|
-
if (this.settings.autoApprove !== false) {
|
|
37704
|
+
if (this.settings.autoApprove !== false && !this.manualAttendance.isAttended()) {
|
|
37605
37705
|
const toolTitle = tc.title || tc.toolCallId || "tool call";
|
|
37606
37706
|
this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
|
|
37607
37707
|
this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
|
|
@@ -37832,6 +37932,15 @@ var AcpProviderInstance = class {
|
|
|
37832
37932
|
this.detectStatusTransition();
|
|
37833
37933
|
}
|
|
37834
37934
|
permissionResolvers = [];
|
|
37935
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
37936
|
+
// this session from the dashboard, auto-approve holds so they can decide on
|
|
37937
|
+
// the permission request themselves. Background workers are never attended →
|
|
37938
|
+
// delegated auto-approve is unaffected.
|
|
37939
|
+
manualAttendance = new ManualAttendanceTracker();
|
|
37940
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
37941
|
+
noteManualInteraction(now = Date.now()) {
|
|
37942
|
+
this.manualAttendance.note(now);
|
|
37943
|
+
}
|
|
37835
37944
|
async resolvePermission(approved) {
|
|
37836
37945
|
const resolver = this.permissionResolvers.shift();
|
|
37837
37946
|
if (resolver) {
|
|
@@ -38989,6 +39098,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38989
39098
|
);
|
|
38990
39099
|
continue;
|
|
38991
39100
|
}
|
|
39101
|
+
const restoredSettings = { ...this.providerLoader.getSettings(normalizedType) };
|
|
39102
|
+
const coordinatorEntry = getCoordinatorForSession(record.runtimeId);
|
|
39103
|
+
if (coordinatorEntry?.meshId) {
|
|
39104
|
+
restoredSettings.meshCoordinatorFor = coordinatorEntry.meshId;
|
|
39105
|
+
}
|
|
38992
39106
|
try {
|
|
38993
39107
|
await this.registerCliInstance(
|
|
38994
39108
|
record.runtimeId,
|
|
@@ -38997,7 +39111,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38997
39111
|
record.workspace,
|
|
38998
39112
|
record.cliArgs,
|
|
38999
39113
|
resolvedProvider,
|
|
39000
|
-
|
|
39114
|
+
restoredSettings,
|
|
39001
39115
|
true,
|
|
39002
39116
|
{
|
|
39003
39117
|
providerSessionId: sessionBinding.providerSessionId,
|