@cabane/companion 0.6.62 → 0.6.63
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/cli.js +57 -11
- package/dist/runtime.js +57 -11
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7173,16 +7173,32 @@ var WAKE_ME_TOOL_NAME = `mcp__${COMPANION_LOCAL_MCP_SERVER}__${WAKE_ME_TOOL}`;
|
|
|
7173
7173
|
var CANCEL_WAKE_TOOL = "cancel_wake";
|
|
7174
7174
|
var CANCEL_WAKE_TOOL_NAME = `mcp__${COMPANION_LOCAL_MCP_SERVER}__${CANCEL_WAKE_TOOL}`;
|
|
7175
7175
|
function createReplyState() {
|
|
7176
|
-
return { answersMessageId: null };
|
|
7176
|
+
return { answersMessageId: null, order: null };
|
|
7177
7177
|
}
|
|
7178
7178
|
function createSendState() {
|
|
7179
|
-
return { agentId: null, message: null };
|
|
7179
|
+
return { agentId: null, message: null, order: null };
|
|
7180
|
+
}
|
|
7181
|
+
function createTurnControlOrder() {
|
|
7182
|
+
let calls = 0;
|
|
7183
|
+
return {
|
|
7184
|
+
next: () => {
|
|
7185
|
+
calls += 1;
|
|
7186
|
+
return calls;
|
|
7187
|
+
}
|
|
7188
|
+
};
|
|
7180
7189
|
}
|
|
7181
7190
|
function createSkipState() {
|
|
7182
7191
|
return { skipped: false, reason: null };
|
|
7183
7192
|
}
|
|
7184
7193
|
function createAskState() {
|
|
7185
|
-
return {
|
|
7194
|
+
return {
|
|
7195
|
+
targetUserId: null,
|
|
7196
|
+
question: null,
|
|
7197
|
+
headline: null,
|
|
7198
|
+
options: null,
|
|
7199
|
+
questions: null,
|
|
7200
|
+
order: null
|
|
7201
|
+
};
|
|
7186
7202
|
}
|
|
7187
7203
|
function createWakeState() {
|
|
7188
7204
|
return { afterSeconds: null, at: null, note: null, cancelled: false };
|
|
@@ -7212,7 +7228,7 @@ function wakeCommitField(state) {
|
|
|
7212
7228
|
}
|
|
7213
7229
|
};
|
|
7214
7230
|
}
|
|
7215
|
-
function createTurnControlMcpServer(sendState, skipState, askState, subAgentCreate, wakeState, replyState) {
|
|
7231
|
+
function createTurnControlMcpServer(sendState, skipState, askState, subAgentCreate, wakeState, replyState, controlOrder) {
|
|
7216
7232
|
return createSdkMcpServer({
|
|
7217
7233
|
name: COMPANION_LOCAL_MCP_SERVER,
|
|
7218
7234
|
version: "0.0.0",
|
|
@@ -7229,6 +7245,7 @@ function createTurnControlMcpServer(sendState, skipState, askState, subAgentCrea
|
|
|
7229
7245
|
async (args) => {
|
|
7230
7246
|
sendState.agentId = args.agentId;
|
|
7231
7247
|
sendState.message = args.message;
|
|
7248
|
+
sendState.order = controlOrder?.next() ?? null;
|
|
7232
7249
|
return {
|
|
7233
7250
|
content: [{ type: "text", text: JSON.stringify({ sent: args.agentId }) }]
|
|
7234
7251
|
};
|
|
@@ -7244,6 +7261,7 @@ function createTurnControlMcpServer(sendState, skipState, askState, subAgentCrea
|
|
|
7244
7261
|
},
|
|
7245
7262
|
async (args) => {
|
|
7246
7263
|
replyState.answersMessageId = args.messageId;
|
|
7264
|
+
replyState.order = controlOrder?.next() ?? null;
|
|
7247
7265
|
return {
|
|
7248
7266
|
content: [
|
|
7249
7267
|
{
|
|
@@ -7326,6 +7344,7 @@ function createTurnControlMcpServer(sendState, skipState, askState, subAgentCrea
|
|
|
7326
7344
|
};
|
|
7327
7345
|
}
|
|
7328
7346
|
askState.targetUserId = args.targetUserId;
|
|
7347
|
+
askState.order = controlOrder?.next() ?? null;
|
|
7329
7348
|
if (hasArray) {
|
|
7330
7349
|
askState.questions = args.questions;
|
|
7331
7350
|
askState.question = null;
|
|
@@ -7889,12 +7908,31 @@ var TurnCommitter = class {
|
|
|
7889
7908
|
// a wordless turn has no answer to bind, and the server's mute-settle
|
|
7890
7909
|
// notice speaks for it.
|
|
7891
7910
|
turnControlFields(kind) {
|
|
7892
|
-
|
|
7911
|
+
const fields = {
|
|
7893
7912
|
...this.answersField(kind),
|
|
7894
7913
|
...this.sendField(),
|
|
7895
7914
|
...this.askField(),
|
|
7896
7915
|
...this.wakeField()
|
|
7897
7916
|
};
|
|
7917
|
+
return { ...fields, ...this.orderField(fields) };
|
|
7918
|
+
}
|
|
7919
|
+
// CT1281: the order the control tools were CALLED, for the addressed rows the
|
|
7920
|
+
// server writes from this one commit. It reports a position only for an intent
|
|
7921
|
+
// that actually made it into the commit — an ask whose payload was incomplete,
|
|
7922
|
+
// or a self-send the committer stripped, contributes no row and so has no place
|
|
7923
|
+
// in the line. An intent with no recorded call (the runtime's auto-declared
|
|
7924
|
+
// reply) is deliberately absent: the server sorts it last, which is what it is.
|
|
7925
|
+
orderField(fields) {
|
|
7926
|
+
const order = {};
|
|
7927
|
+
const replyOrder = this.deps.replyState.order;
|
|
7928
|
+
if (fields.answersMessageId !== void 0 && replyOrder !== null) order.reply = replyOrder;
|
|
7929
|
+
if (fields.dispatch !== void 0 && this.deps.sendState.order !== null) {
|
|
7930
|
+
order.send = this.deps.sendState.order;
|
|
7931
|
+
}
|
|
7932
|
+
if (fields.ask !== void 0 && this.deps.askState.order !== null) {
|
|
7933
|
+
order.ask = this.deps.askState.order;
|
|
7934
|
+
}
|
|
7935
|
+
return Object.keys(order).length > 0 ? { turnControlOrder: order } : {};
|
|
7898
7936
|
}
|
|
7899
7937
|
// The declared reply: explicit `reply_to` first, else the runtime's own
|
|
7900
7938
|
// declaration for the turn that just answers — see
|
|
@@ -8353,6 +8391,7 @@ ${reason}`,
|
|
|
8353
8391
|
const askState = createAskState();
|
|
8354
8392
|
const wakeState = createWakeState();
|
|
8355
8393
|
const replyState = createReplyState();
|
|
8394
|
+
const controlOrder = createTurnControlOrder();
|
|
8356
8395
|
let spawnedSubAgent = false;
|
|
8357
8396
|
const subAgentCreate = async (args) => {
|
|
8358
8397
|
const dispatchTarget = args.agentId ?? payload.agentId;
|
|
@@ -8384,7 +8423,8 @@ ${reason}`,
|
|
|
8384
8423
|
askState,
|
|
8385
8424
|
subAgentCreate,
|
|
8386
8425
|
wakeState,
|
|
8387
|
-
replyState
|
|
8426
|
+
replyState,
|
|
8427
|
+
controlOrder
|
|
8388
8428
|
);
|
|
8389
8429
|
const request = buildCompanionTurnRequest({
|
|
8390
8430
|
turnContext,
|
|
@@ -8503,11 +8543,12 @@ ${reason}`,
|
|
|
8503
8543
|
signal: abortController.signal,
|
|
8504
8544
|
log: turnLog,
|
|
8505
8545
|
nextSeq,
|
|
8506
|
-
// The committer reads this at commit to
|
|
8507
|
-
//
|
|
8546
|
+
// The committer reads this at commit to carry the addressed send on the
|
|
8547
|
+
// terminal row; the server writes the send itself as a distinct message.
|
|
8508
8548
|
sendState,
|
|
8509
|
-
// CT326: likewise the ask payload
|
|
8510
|
-
//
|
|
8549
|
+
// CT326: likewise the ask payload. CT1281: the server writes the ask as its
|
|
8550
|
+
// own addressed message to the human — which ENQUEUES like any other send —
|
|
8551
|
+
// and creates the `asks` row against that carrier, not against turn speech.
|
|
8511
8552
|
askState,
|
|
8512
8553
|
// CT442: likewise the wake payload — attached to the `final` row so the
|
|
8513
8554
|
// server arms the wake schedule atomically with the reply it rode on.
|
|
@@ -8532,6 +8573,7 @@ ${reason}`,
|
|
|
8532
8573
|
);
|
|
8533
8574
|
if (intent.ask) {
|
|
8534
8575
|
askState.targetUserId = intent.ask.targetUserId;
|
|
8576
|
+
askState.order = intent.askOrder ?? null;
|
|
8535
8577
|
if (intent.ask.questions && intent.ask.questions.length > 0) {
|
|
8536
8578
|
askState.questions = intent.ask.questions;
|
|
8537
8579
|
askState.question = null;
|
|
@@ -8560,8 +8602,12 @@ ${reason}`,
|
|
|
8560
8602
|
if (intent.sendAgentId && intent.sendBody) {
|
|
8561
8603
|
sendState.agentId = intent.sendAgentId;
|
|
8562
8604
|
sendState.message = intent.sendBody;
|
|
8605
|
+
sendState.order = intent.sendOrder ?? null;
|
|
8606
|
+
}
|
|
8607
|
+
if (intent.answersMessageId) {
|
|
8608
|
+
replyState.answersMessageId = intent.answersMessageId;
|
|
8609
|
+
replyState.order = intent.replyOrder ?? null;
|
|
8563
8610
|
}
|
|
8564
|
-
if (intent.answersMessageId) replyState.answersMessageId = intent.answersMessageId;
|
|
8565
8611
|
if (intent.skipped) {
|
|
8566
8612
|
skipState.skipped = true;
|
|
8567
8613
|
skipState.reason = intent.skipReason;
|
package/dist/runtime.js
CHANGED
|
@@ -6672,16 +6672,32 @@ var WAKE_ME_TOOL_NAME = `mcp__${COMPANION_LOCAL_MCP_SERVER}__${WAKE_ME_TOOL}`;
|
|
|
6672
6672
|
var CANCEL_WAKE_TOOL = "cancel_wake";
|
|
6673
6673
|
var CANCEL_WAKE_TOOL_NAME = `mcp__${COMPANION_LOCAL_MCP_SERVER}__${CANCEL_WAKE_TOOL}`;
|
|
6674
6674
|
function createReplyState() {
|
|
6675
|
-
return { answersMessageId: null };
|
|
6675
|
+
return { answersMessageId: null, order: null };
|
|
6676
6676
|
}
|
|
6677
6677
|
function createSendState() {
|
|
6678
|
-
return { agentId: null, message: null };
|
|
6678
|
+
return { agentId: null, message: null, order: null };
|
|
6679
|
+
}
|
|
6680
|
+
function createTurnControlOrder() {
|
|
6681
|
+
let calls = 0;
|
|
6682
|
+
return {
|
|
6683
|
+
next: () => {
|
|
6684
|
+
calls += 1;
|
|
6685
|
+
return calls;
|
|
6686
|
+
}
|
|
6687
|
+
};
|
|
6679
6688
|
}
|
|
6680
6689
|
function createSkipState() {
|
|
6681
6690
|
return { skipped: false, reason: null };
|
|
6682
6691
|
}
|
|
6683
6692
|
function createAskState() {
|
|
6684
|
-
return {
|
|
6693
|
+
return {
|
|
6694
|
+
targetUserId: null,
|
|
6695
|
+
question: null,
|
|
6696
|
+
headline: null,
|
|
6697
|
+
options: null,
|
|
6698
|
+
questions: null,
|
|
6699
|
+
order: null
|
|
6700
|
+
};
|
|
6685
6701
|
}
|
|
6686
6702
|
function createWakeState() {
|
|
6687
6703
|
return { afterSeconds: null, at: null, note: null, cancelled: false };
|
|
@@ -6711,7 +6727,7 @@ function wakeCommitField(state) {
|
|
|
6711
6727
|
}
|
|
6712
6728
|
};
|
|
6713
6729
|
}
|
|
6714
|
-
function createTurnControlMcpServer(sendState, skipState, askState, subAgentCreate, wakeState, replyState) {
|
|
6730
|
+
function createTurnControlMcpServer(sendState, skipState, askState, subAgentCreate, wakeState, replyState, controlOrder) {
|
|
6715
6731
|
return createSdkMcpServer({
|
|
6716
6732
|
name: COMPANION_LOCAL_MCP_SERVER,
|
|
6717
6733
|
version: "0.0.0",
|
|
@@ -6728,6 +6744,7 @@ function createTurnControlMcpServer(sendState, skipState, askState, subAgentCrea
|
|
|
6728
6744
|
async (args) => {
|
|
6729
6745
|
sendState.agentId = args.agentId;
|
|
6730
6746
|
sendState.message = args.message;
|
|
6747
|
+
sendState.order = controlOrder?.next() ?? null;
|
|
6731
6748
|
return {
|
|
6732
6749
|
content: [{ type: "text", text: JSON.stringify({ sent: args.agentId }) }]
|
|
6733
6750
|
};
|
|
@@ -6743,6 +6760,7 @@ function createTurnControlMcpServer(sendState, skipState, askState, subAgentCrea
|
|
|
6743
6760
|
},
|
|
6744
6761
|
async (args) => {
|
|
6745
6762
|
replyState.answersMessageId = args.messageId;
|
|
6763
|
+
replyState.order = controlOrder?.next() ?? null;
|
|
6746
6764
|
return {
|
|
6747
6765
|
content: [
|
|
6748
6766
|
{
|
|
@@ -6825,6 +6843,7 @@ function createTurnControlMcpServer(sendState, skipState, askState, subAgentCrea
|
|
|
6825
6843
|
};
|
|
6826
6844
|
}
|
|
6827
6845
|
askState.targetUserId = args.targetUserId;
|
|
6846
|
+
askState.order = controlOrder?.next() ?? null;
|
|
6828
6847
|
if (hasArray) {
|
|
6829
6848
|
askState.questions = args.questions;
|
|
6830
6849
|
askState.question = null;
|
|
@@ -7388,12 +7407,31 @@ var TurnCommitter = class {
|
|
|
7388
7407
|
// a wordless turn has no answer to bind, and the server's mute-settle
|
|
7389
7408
|
// notice speaks for it.
|
|
7390
7409
|
turnControlFields(kind) {
|
|
7391
|
-
|
|
7410
|
+
const fields = {
|
|
7392
7411
|
...this.answersField(kind),
|
|
7393
7412
|
...this.sendField(),
|
|
7394
7413
|
...this.askField(),
|
|
7395
7414
|
...this.wakeField()
|
|
7396
7415
|
};
|
|
7416
|
+
return { ...fields, ...this.orderField(fields) };
|
|
7417
|
+
}
|
|
7418
|
+
// CT1281: the order the control tools were CALLED, for the addressed rows the
|
|
7419
|
+
// server writes from this one commit. It reports a position only for an intent
|
|
7420
|
+
// that actually made it into the commit — an ask whose payload was incomplete,
|
|
7421
|
+
// or a self-send the committer stripped, contributes no row and so has no place
|
|
7422
|
+
// in the line. An intent with no recorded call (the runtime's auto-declared
|
|
7423
|
+
// reply) is deliberately absent: the server sorts it last, which is what it is.
|
|
7424
|
+
orderField(fields) {
|
|
7425
|
+
const order = {};
|
|
7426
|
+
const replyOrder = this.deps.replyState.order;
|
|
7427
|
+
if (fields.answersMessageId !== void 0 && replyOrder !== null) order.reply = replyOrder;
|
|
7428
|
+
if (fields.dispatch !== void 0 && this.deps.sendState.order !== null) {
|
|
7429
|
+
order.send = this.deps.sendState.order;
|
|
7430
|
+
}
|
|
7431
|
+
if (fields.ask !== void 0 && this.deps.askState.order !== null) {
|
|
7432
|
+
order.ask = this.deps.askState.order;
|
|
7433
|
+
}
|
|
7434
|
+
return Object.keys(order).length > 0 ? { turnControlOrder: order } : {};
|
|
7397
7435
|
}
|
|
7398
7436
|
// The declared reply: explicit `reply_to` first, else the runtime's own
|
|
7399
7437
|
// declaration for the turn that just answers — see
|
|
@@ -7852,6 +7890,7 @@ ${reason}`,
|
|
|
7852
7890
|
const askState = createAskState();
|
|
7853
7891
|
const wakeState = createWakeState();
|
|
7854
7892
|
const replyState = createReplyState();
|
|
7893
|
+
const controlOrder = createTurnControlOrder();
|
|
7855
7894
|
let spawnedSubAgent = false;
|
|
7856
7895
|
const subAgentCreate = async (args) => {
|
|
7857
7896
|
const dispatchTarget = args.agentId ?? payload.agentId;
|
|
@@ -7883,7 +7922,8 @@ ${reason}`,
|
|
|
7883
7922
|
askState,
|
|
7884
7923
|
subAgentCreate,
|
|
7885
7924
|
wakeState,
|
|
7886
|
-
replyState
|
|
7925
|
+
replyState,
|
|
7926
|
+
controlOrder
|
|
7887
7927
|
);
|
|
7888
7928
|
const request = buildCompanionTurnRequest({
|
|
7889
7929
|
turnContext,
|
|
@@ -8002,11 +8042,12 @@ ${reason}`,
|
|
|
8002
8042
|
signal: abortController.signal,
|
|
8003
8043
|
log: turnLog,
|
|
8004
8044
|
nextSeq,
|
|
8005
|
-
// The committer reads this at commit to
|
|
8006
|
-
//
|
|
8045
|
+
// The committer reads this at commit to carry the addressed send on the
|
|
8046
|
+
// terminal row; the server writes the send itself as a distinct message.
|
|
8007
8047
|
sendState,
|
|
8008
|
-
// CT326: likewise the ask payload
|
|
8009
|
-
//
|
|
8048
|
+
// CT326: likewise the ask payload. CT1281: the server writes the ask as its
|
|
8049
|
+
// own addressed message to the human — which ENQUEUES like any other send —
|
|
8050
|
+
// and creates the `asks` row against that carrier, not against turn speech.
|
|
8010
8051
|
askState,
|
|
8011
8052
|
// CT442: likewise the wake payload — attached to the `final` row so the
|
|
8012
8053
|
// server arms the wake schedule atomically with the reply it rode on.
|
|
@@ -8031,6 +8072,7 @@ ${reason}`,
|
|
|
8031
8072
|
);
|
|
8032
8073
|
if (intent.ask) {
|
|
8033
8074
|
askState.targetUserId = intent.ask.targetUserId;
|
|
8075
|
+
askState.order = intent.askOrder ?? null;
|
|
8034
8076
|
if (intent.ask.questions && intent.ask.questions.length > 0) {
|
|
8035
8077
|
askState.questions = intent.ask.questions;
|
|
8036
8078
|
askState.question = null;
|
|
@@ -8059,8 +8101,12 @@ ${reason}`,
|
|
|
8059
8101
|
if (intent.sendAgentId && intent.sendBody) {
|
|
8060
8102
|
sendState.agentId = intent.sendAgentId;
|
|
8061
8103
|
sendState.message = intent.sendBody;
|
|
8104
|
+
sendState.order = intent.sendOrder ?? null;
|
|
8105
|
+
}
|
|
8106
|
+
if (intent.answersMessageId) {
|
|
8107
|
+
replyState.answersMessageId = intent.answersMessageId;
|
|
8108
|
+
replyState.order = intent.replyOrder ?? null;
|
|
8062
8109
|
}
|
|
8063
|
-
if (intent.answersMessageId) replyState.answersMessageId = intent.answersMessageId;
|
|
8064
8110
|
if (intent.skipped) {
|
|
8065
8111
|
skipState.skipped = true;
|
|
8066
8112
|
skipState.reason = intent.skipReason;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.63",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The Cabane Companion (headless): connect a coding agent on your machine to your Cabane workspace as a responder — drive work against your own codebase, files, and MCP servers without putting any of it in Cabane.",
|
|
6
6
|
"license": "UNLICENSED",
|