tines 0.0.158 → 0.0.160

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.
Files changed (2) hide show
  1. package/dist/index.js +109 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6611,6 +6611,32 @@ function registerEvents(program3) {
6611
6611
  // src/commands/projects.ts
6612
6612
  function register6(program3) {
6613
6613
  const projects = program3.command("projects").description("Manage projects");
6614
+ withCommon(
6615
+ projects.command("starters").description("List built-in project starters and their inputs")
6616
+ ).action(async (opts) => {
6617
+ const response = await client(opts).listStarters();
6618
+ if (opts.json) return printJson(response);
6619
+ for (const starter of response.items) {
6620
+ console.log(`${starter.id} \u2014 ${starter.name}`);
6621
+ console.log(` ${starter.description}`);
6622
+ for (const input of starter.inputs) {
6623
+ console.log(
6624
+ ` --${inputFlag(input)}${input.required ? " (required)" : " (optional)"} \u2014 ${input.description ?? input.label}`
6625
+ );
6626
+ }
6627
+ for (const workflow of starter.creates.workflows) {
6628
+ console.log(
6629
+ ` workflow: ${workflow.name}${workflow.default ? " (default)" : ""} \u2014 ${workflow.states.join(" \u2192 ")}`
6630
+ );
6631
+ }
6632
+ for (const item of starter.creates.context) console.log(` ${item.kind}: ${item.name}`);
6633
+ if (starter.creates.first_issue) {
6634
+ const issue = starter.creates.first_issue;
6635
+ console.log(` first issue: ${issue.title} \u2014 ${issue.state} (${issue.workflow})`);
6636
+ }
6637
+ if (isBlank(starter)) console.log(" requires --prompt or --no-prompt when creating");
6638
+ }
6639
+ });
6614
6640
  withList(
6615
6641
  projects.command("list").description("List projects").option("--archived", "include archived projects (hidden by default)")
6616
6642
  ).action(async (opts) => {
@@ -6634,29 +6660,96 @@ function register6(program3) {
6634
6660
  });
6635
6661
  });
6636
6662
  withCommon(
6637
- projects.command("create <name>").description("Create a project (with its initial context prompt)").option("-d, --description <text>", "project description").option("-w, --default-workflow <id-or-name>", "default workflow for new issues").option(
6663
+ projects.command("create <name>").description(
6664
+ "Create a project; nonblank starters supply a conventions template unless --prompt or --no-prompt overrides it"
6665
+ ).option("-d, --description <text>", "project description").option(
6666
+ "-w, --default-workflow <id-or-name>",
6667
+ "default workflow for new issues (conflicts with a starter that sets one)"
6668
+ ).option("--starter <id>", "built-in starter (discover with `tines projects starters`)").option("--repo <url>", "repository URL for the code starter").option("--branch <branch>", "repository branch for the code starter").option("--brief <text>", "planning brief for the plan starter").option(
6638
6669
  "--prompt <md>",
6639
- "initial conventions prompt, stitched into every issue's agent prompt: inline Markdown or @file"
6640
- ).option("--no-prompt", "create without an initial prompt")
6670
+ "override the starter's conventions template: inline Markdown or @file"
6671
+ ).option(
6672
+ "--no-prompt",
6673
+ "omit the starter's conventions template (other starter context remains)"
6674
+ )
6641
6675
  ).action(
6642
6676
  async (name2, opts) => {
6643
- if (opts.prompt === void 0 || opts.prompt === true) {
6677
+ const prompt = typeof opts.prompt === "string" ? readBodyValue(opts.prompt) : void 0;
6678
+ const suppliedInputs = [
6679
+ ["repo_url", "--repo", opts.repo],
6680
+ ["repo_branch", "--branch", opts.branch],
6681
+ ["brief", "--brief", opts.brief]
6682
+ ];
6683
+ if (!opts.starter && suppliedInputs.some(([, , value]) => value !== void 0)) {
6644
6684
  die(
6645
- 'every issue in a project inherits its context \u2014 give the project an initial prompt:\n --prompt "<markdown>" house conventions, inline or @file\n --no-prompt create without one (add later: tines context create -k prompt -n conventions -p <name> --body \u2026)'
6685
+ "starter input flags require --starter (discover choices with `tines projects starters`)"
6646
6686
  );
6647
6687
  }
6648
6688
  const api = client(opts);
6689
+ let starter;
6690
+ let starterRequest;
6691
+ if (opts.starter) {
6692
+ const response = await api.listStarters();
6693
+ starter = response.items.find((item) => item.id === opts.starter);
6694
+ if (!starter) {
6695
+ die(
6696
+ `unknown starter "${opts.starter}"; choose ${response.items.map((item) => item.id).join(", ")} (see \`tines projects starters\`)`
6697
+ );
6698
+ }
6699
+ const declared = new Map(starter.inputs.map((input) => [input.key, input]));
6700
+ for (const [key, flag, value] of suppliedInputs) {
6701
+ if (value !== void 0 && !declared.has(key))
6702
+ die(`${flag} is not used by starter "${starter.id}"`);
6703
+ }
6704
+ const inputs = {};
6705
+ for (const [key, , value] of suppliedInputs) {
6706
+ if (value !== void 0 && declared.has(key)) inputs[key] = value.trim();
6707
+ }
6708
+ for (const input of starter.inputs) {
6709
+ const value = inputs[input.key] ?? "";
6710
+ if (input.required && !value)
6711
+ die(`starter "${starter.id}" requires --${inputFlag(input)}`);
6712
+ const max = input.max ?? 1e4;
6713
+ if (value.length > max) die(`--${inputFlag(input)} is longer than ${max} characters`);
6714
+ }
6715
+ if (starter.creates.workflows.some((workflow) => workflow.default) && opts.defaultWorkflow) {
6716
+ die(`starter "${starter.id}" sets the default workflow; do not pass --default-workflow`);
6717
+ }
6718
+ starterRequest = { id: starter.id, inputs };
6719
+ }
6720
+ if ((!starter || isBlank(starter)) && (opts.prompt === void 0 || opts.prompt === true)) {
6721
+ die(
6722
+ 'every issue in a project inherits its context \u2014 give the project an initial prompt:\n --prompt "<markdown>" house conventions, inline or @file\n --no-prompt create without one (add later: tines context create -k prompt -n conventions -p <name> --body \u2026)'
6723
+ );
6724
+ }
6649
6725
  const workflowId = opts.defaultWorkflow ? (await resolveWorkflow(api, opts.defaultWorkflow)).id : void 0;
6650
- const project = await api.createProject({
6726
+ const body = {
6651
6727
  name: name2,
6652
6728
  description: opts.description,
6653
6729
  default_workflow_id: workflowId,
6654
- initial_prompt: typeof opts.prompt === "string" ? readBodyValue(opts.prompt) : void 0
6655
- });
6730
+ ...typeof opts.prompt === "string" ? { initial_prompt: prompt } : opts.prompt === false ? { initial_prompt: "" } : {},
6731
+ ...starterRequest ? { starter: starterRequest } : {}
6732
+ };
6733
+ const project = await api.createProject(body);
6656
6734
  if (opts.json) return printJson(project);
6657
6735
  console.log(
6658
6736
  `created project "${project.name}" (${project.id})${typeof opts.prompt === "string" ? ' with its "conventions" prompt' : ""}`
6659
6737
  );
6738
+ if (project.starter) {
6739
+ for (const workflow of project.starter.workflows) {
6740
+ console.log(
6741
+ `workflow: ${workflow.name} (${workflow.id})${workflow.reused ? " \u2014 reused" : ""}`
6742
+ );
6743
+ }
6744
+ for (const item of project.starter.context)
6745
+ console.log(`context: ${item.kind} \u201C${item.name}\u201D`);
6746
+ if (project.starter.first_issue) {
6747
+ const issue = project.starter.first_issue;
6748
+ console.log(`first issue: ${issue.ref} \u2014 ${issue.state_name}`);
6749
+ console.log(`tines issues show "${issue.ref}"`);
6750
+ }
6751
+ console.log(`Next: get an agent running \u2014 ${resolveUrl(opts).replace(/\/$/, "")}/agents`);
6752
+ }
6660
6753
  }
6661
6754
  );
6662
6755
  withCommon(projects.command("show <id-or-name>").description("Show a project")).action(
@@ -6730,6 +6823,14 @@ default workflow: ${defaultWorkflow}`);
6730
6823
  console.log(`deleted project "${project.name}" (${project.id})`);
6731
6824
  });
6732
6825
  }
6826
+ function inputFlag(input) {
6827
+ if (input.key === "repo_url") return "repo";
6828
+ if (input.key === "repo_branch") return "branch";
6829
+ return input.key.replaceAll("_", "-");
6830
+ }
6831
+ function isBlank(starter) {
6832
+ return starter.creates.workflows.length === 0 && starter.creates.context.length === 0 && starter.creates.first_issue === null;
6833
+ }
6733
6834
 
6734
6835
  // src/commands/routing.ts
6735
6836
  async function resolveRoutingScope(api, opts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tines",
3
- "version": "0.0.158",
3
+ "version": "0.0.160",
4
4
  "description": "CLI for Tines, an orchestration layer for AI agents",
5
5
  "repository": {
6
6
  "type": "git",