@neverquits/nq 0.1.2 → 0.1.4

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/bin/nq.mjs CHANGED
@@ -28,20 +28,20 @@ function printHelp() {
28
28
  nq — NeverQuits CLI
29
29
 
30
30
  Usage:
31
- nq login Log in with your access token
32
- nq pull <agent> --org <orgId> Clone agent workspace
33
- nq push [-m "message"] Commit and push changes
34
- nq logout Clear stored credentials
35
- nq status Show current config
31
+ nq login Log in with your access token
32
+ nq pull <hiredAgentId> Clone the agent's workspace
33
+ nq push [-m "message"] Commit and push changes
34
+ nq logout Clear stored credentials
35
+ nq status Show current config
36
36
 
37
37
  Options:
38
- nq pull <agent> --org <id> --session <id> Also write .mcp.json
39
- nq pull <agent> --org <id> --dir <path> Custom clone directory
40
- nq push --message "my changes" Custom commit message
38
+ nq pull <hiredAgentId> --session <id> Also write .mcp.json
39
+ nq pull <hiredAgentId> --dir <path> Custom clone directory
40
+ nq push --message "my changes" Custom commit message
41
41
 
42
42
  Examples:
43
43
  nq login
44
- nq pull alex --org acme123 --session sess_abc
44
+ nq pull cmpl6d28g0004fy3icu397lqk
45
45
  nq push -m "updated research notes"
46
46
  `)
47
47
  }
@@ -81,13 +81,13 @@ async function main() {
81
81
 
82
82
  if (command === 'pull') {
83
83
  const { flags, positional } = parseFlags(args.slice(1))
84
- const agentKey = positional[0]
85
- if (!agentKey) {
86
- console.error('Usage: nq pull <agent> --org <orgId>')
84
+ const target = positional[0]
85
+ if (!target) {
86
+ console.error('Usage: nq pull <hiredAgentId>')
87
87
  process.exit(1)
88
88
  }
89
89
  const { pull } = await import('../lib/commands/pull.mjs')
90
- await pull(agentKey, {
90
+ await pull(target, {
91
91
  org: flags.org,
92
92
  session: flags.session,
93
93
  dir: flags.dir,
@@ -1,29 +1,40 @@
1
1
  import { execSync } from 'node:child_process'
2
2
  import { existsSync, writeFileSync } from 'node:fs'
3
- import { join, resolve } from 'node:path'
3
+ import { join, resolve, dirname } from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
4
5
  import { apiFetch, getToken } from '../api.mjs'
5
6
  import { getApiUrl } from '../config.mjs'
6
7
 
7
- export async function pull(agentKey, options) {
8
- const orgId = options.org
9
- if (!orgId) {
10
- console.error('Missing --org flag. Usage: nq pull <agent> --org <orgId>')
8
+ const NQ_BIN = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', 'bin', 'nq.mjs')
9
+ const NODE_BIN = process.execPath
10
+
11
+ export async function pull(positional, options) {
12
+ // Two call shapes:
13
+ // nq pull <hiredAgentId> (preferred)
14
+ // nq pull <agentKey> --org <orgId> (legacy)
15
+ // Distinguish by whether --org was passed.
16
+ const useLegacy = Boolean(options.org)
17
+ const body = useLegacy
18
+ ? { orgId: options.org, agentKey: positional }
19
+ : { hiredAgentId: positional }
20
+
21
+ if (!positional) {
22
+ console.error('Usage: nq pull <hiredAgentId>')
23
+ console.error(' or: nq pull <agentKey> --org <orgId> (legacy)')
11
24
  process.exit(1)
12
25
  }
13
26
 
14
- const sessionId = options.session
15
- const dir = options.dir ?? `${orgId}-${agentKey}`
16
- const dest = resolve(dir)
17
-
18
27
  console.log()
19
- console.log(` Pulling workspace: ${orgId}/${agentKey}`)
28
+ console.log(useLegacy
29
+ ? ` Pulling workspace: ${body.orgId}/${body.agentKey}`
30
+ : ` Pulling workspace: ${positional}`)
20
31
 
21
32
  // Ask the backend for a fresh installation token + the repo identifier.
22
33
  // The token is short-lived; we bake it into the clone URL once and then
23
34
  // configure a credential helper so future pushes/pulls mint a new one.
24
35
  const tokenRes = await apiFetch('/api/workspace/install-token', {
25
36
  method: 'POST',
26
- body: JSON.stringify({ orgId, agentKey }),
37
+ body: JSON.stringify(body),
27
38
  })
28
39
  if (tokenRes.status === 404) {
29
40
  console.error(' No workspace repo found. Has onboarding been completed for this org?')
@@ -33,7 +44,23 @@ export async function pull(agentKey, options) {
33
44
  console.error(` Failed to mint install token: ${tokenRes.status}`)
34
45
  process.exit(1)
35
46
  }
36
- const { token, username, githubOrg, repoName } = await tokenRes.json()
47
+ const {
48
+ token,
49
+ username,
50
+ githubOrg,
51
+ repoName,
52
+ orgId: resolvedOrgId,
53
+ agentKey: resolvedAgentKey,
54
+ } = await tokenRes.json()
55
+
56
+ // The server always echoes back resolvedOrgId + resolvedAgentKey so the
57
+ // CLI can stash them in .git/config for the credential helper.
58
+ const orgId = resolvedOrgId ?? options.org
59
+ const agentKey = resolvedAgentKey ?? positional
60
+
61
+ const sessionId = options.session
62
+ const dir = options.dir ?? `${orgId}-${agentKey}`
63
+ const dest = resolve(dir)
37
64
 
38
65
  const gitDir = join(dest, '.git')
39
66
 
@@ -70,7 +97,7 @@ export async function pull(agentKey, options) {
70
97
  console.log(' Wrote .mcp.json')
71
98
  } else {
72
99
  console.log(' Skipped .mcp.json (no --session). Create a session first, then run:')
73
- console.log(` nq pull ${agentKey} --org ${orgId} --session <sessionId>`)
100
+ console.log(` nq pull ${positional} --session <sessionId>`)
74
101
  }
75
102
 
76
103
  console.log()
@@ -100,14 +127,17 @@ function setRemote(dest, url) {
100
127
  }
101
128
 
102
129
  function configureCredentialHelper(dest, orgId, agentKey) {
103
- // The helper is invoked by git as `nq credential-helper get` (etc).
104
- // Stash the workspace identifiers so the helper knows what to ask for.
130
+ // The helper is invoked by git during a github.com auth challenge.
131
+ // We point at the *absolute* path of this nq install (node binary +
132
+ // bin/nq.mjs) so the helper works regardless of whether `nq` is on
133
+ // the user's PATH — e.g. when they invoked us via `npx`.
134
+ const helperCmd = `${shArg(NODE_BIN)} ${shArg(NQ_BIN)} credential-helper`
105
135
  const cmds = [
106
136
  ['nq.orgId', orgId],
107
137
  ['nq.agentKey', agentKey],
108
138
  // Per-host helper, applied only inside this repo via --local config.
109
139
  // The '!' prefix tells git to run it as a shell command.
110
- ['credential.https://github.com.helper', '!nq credential-helper'],
140
+ ['credential.https://github.com.helper', `!${helperCmd}`],
111
141
  ]
112
142
  for (const [k, v] of cmds) {
113
143
  execSync(`git config --local ${shArg(k)} ${shArg(v)}`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neverquits/nq",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "NeverQuits CLI — workspace setup for AI agent operators",
5
5
  "type": "module",
6
6
  "bin": {