talentos 1.1.3 → 1.1.5

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.
@@ -1,6 +1,7 @@
1
1
  import { execFile, spawn } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
- import { rm } from "node:fs/promises";
3
+ import { mkdtemp, rm } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
4
5
  import { dirname, join } from "node:path";
5
6
  import { createInterface } from "node:readline";
6
7
  import { fileURLToPath } from "node:url";
@@ -25,6 +26,8 @@ const CHILD_ENV = [
25
26
  "CODEX_HOME",
26
27
  "CLAUDE_CONFIG_DIR",
27
28
  ];
29
+ // Shared with the preflight: older Codex parses agents.enabled as a role.
30
+ const CODEX_ROOM_GATES = ["agents.enabled=false", "features.goals=false"];
28
31
  const CLAUDE_VERSION = /^\d+\.\d+\.\d+/u;
29
32
  const CODEX_VERSION = /\b\d+\.\d+\.\d+\b/u;
30
33
  const DONT_ASK = /\bdontAsk\b/u;
@@ -103,6 +106,21 @@ export async function verifyCodex(configured) {
103
106
  }
104
107
  if (version !== "unknown") {
105
108
  await codexRoomCatalog(binary);
109
+ const directory = await mkdtemp(join(tmpdir(), "talentos-codex-probe-"));
110
+ try {
111
+ await execute(binary, [
112
+ ...CODEX_ROOM_GATES.flatMap((gate) => ["-c", gate]),
113
+ "features",
114
+ "list",
115
+ ], {
116
+ ...options,
117
+ cwd: directory,
118
+ env: { ...options.env, CODEX_HOME: directory },
119
+ });
120
+ }
121
+ finally {
122
+ await rm(directory, { recursive: true, force: true });
123
+ }
106
124
  return;
107
125
  }
108
126
  }
@@ -261,6 +279,8 @@ export async function runProvider(input) {
261
279
  "features.plugins=false",
262
280
  "-c",
263
281
  "features.multi_agent=false",
282
+ // Codex also gates collaboration separately from the legacy feature.
283
+ ...CODEX_ROOM_GATES.flatMap((gate) => ["-c", gate]),
264
284
  "-c",
265
285
  "features.skip_host_skill_discovery=true",
266
286
  "-c",
@@ -84,7 +84,7 @@ export async function serveAgent(config, directory, version, stop, verify) {
84
84
  const response = await gateway.request("/agent-gateway/heartbeat", { cliVersion: version }, signal);
85
85
  if (response) {
86
86
  minimum = response.cliMinVersion;
87
- if (response.pendingJobs > 0 || minimum !== version) {
87
+ if (response.pendingJobs > 0 || needsUpdate(version, minimum)) {
88
88
  wake();
89
89
  }
90
90
  }
@@ -12,6 +12,7 @@ import { homeDir } from "../install.js";
12
12
  import { defaultDeviceName, hashKey, mintKey } from "../login.js";
13
13
  import { resolveProviderBinary } from "../provider-binary.js";
14
14
  const MAX_PREVIOUS_AGENT_IDS = 100;
15
+ const REMOVED_AGENT_NOTICE = "removed in TalentOS; run talentos agent link to reconnect";
15
16
  export async function runAgent(parsed, dependencies = {}) {
16
17
  switch (parsed.action) {
17
18
  case "link": {
@@ -56,6 +57,17 @@ export async function runAgent(parsed, dependencies = {}) {
56
57
  let failed = 0;
57
58
  for (const agent of agents) {
58
59
  try {
60
+ try {
61
+ await fetchAgentStatus(agent);
62
+ }
63
+ catch (error) {
64
+ if (agentAccessEnded(error)) {
65
+ await uninstallAgentService(agent, { home: dependencies.home });
66
+ emit(redactAgentOutput(`${agent.name} (${agent.agentId}): ${REMOVED_AGENT_NOTICE}.`, [agent.apiKey]));
67
+ continue;
68
+ }
69
+ // Repair remains available offline or before the status route ships.
70
+ }
59
71
  agent.providerPath = (dependencies.resolveBinary ?? resolveProviderBinary)(agent.provider);
60
72
  (dependencies.probe ?? inspectProvider)(agent.provider, agent.providerPath);
61
73
  await storeAgent(agent, dependencies.home);
@@ -205,13 +217,13 @@ async function showAgents(parsed) {
205
217
  });
206
218
  }
207
219
  catch (error) {
220
+ const removed = agentAccessEnded(error);
208
221
  rows.push({
209
222
  agentId: agent.agentId,
210
223
  name: redactAgentOutput(agent.name),
211
224
  provider: agent.provider,
212
- state: error instanceof AgentHttpError && error.status === 401
213
- ? "disconnected"
214
- : "unreachable",
225
+ state: removed ? "removed" : "unreachable",
226
+ hint: removed ? REMOVED_AGENT_NOTICE : undefined,
215
227
  lastSeenAt: null,
216
228
  });
217
229
  }
@@ -221,10 +233,19 @@ async function showAgents(parsed) {
221
233
  }
222
234
  else {
223
235
  emit(rows.length
224
- ? renderTable(["Agent", "Provider", "Status", "ID"], rows.map((row) => [row.name, row.provider, row.state, row.agentId]))
236
+ ? renderTable(["Agent", "Provider", "Status", "ID"], rows.map((row) => [
237
+ row.name,
238
+ row.provider,
239
+ row.hint ?? row.state,
240
+ row.agentId,
241
+ ]))
225
242
  : "No agents linked on this machine. Get a setup prompt from TalentOS.");
226
243
  }
227
244
  }
245
+ function agentAccessEnded(error) {
246
+ return (error instanceof AgentHttpError &&
247
+ (error.status === 401 || error.status === 410));
248
+ }
228
249
  async function unlinkLocal(parsed) {
229
250
  const agents = await selectAgents(parsed, true);
230
251
  const agent = agents[0];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "talentos",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "type": "module",
5
5
  "description": "TalentOS CLI: push and pull skills, read and write team memory, and delegate work to your Talent from any coding agent.",
6
6
  "repository": {